Skip to content

Commit fec3b50

Browse files
authored
Add read objects for dns related MAAS entities (#292)
1 parent 7c1374b commit fec3b50

File tree

9 files changed

+288
-1
lines changed

9 files changed

+288
-1
lines changed

maas/client/facade.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,20 @@ def devices(origin):
104104
"list": origin.Devices.read,
105105
}
106106

107+
@facade
108+
def dnsresources(origin):
109+
return {
110+
"get": origin.DNSResource.read,
111+
"list": origin.DNSResources.read,
112+
}
113+
114+
@facade
115+
def dnsresourcerecords(origin):
116+
return {
117+
"get": origin.DNSResourceRecord.read,
118+
"list": origin.DNSResourceRecords.read,
119+
}
120+
107121
@facade
108122
def domains(origin):
109123
return {
@@ -172,6 +186,12 @@ def ip_ranges(origin):
172186
"list": origin.IPRanges.read,
173187
}
174188

189+
@facade
190+
def ip_addresses(origin):
191+
return {
192+
"list": origin.IPAddresses.read,
193+
}
194+
175195
@facade
176196
def maas(origin):
177197
attrs = (

maas/client/viscera/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1168,6 +1168,8 @@ def __init__(self, session):
11681168
".boot_sources",
11691169
".controllers",
11701170
".devices",
1171+
".dnsresources",
1172+
".dnsresourcerecords",
11711173
".domains",
11721174
".events",
11731175
".subnets",
@@ -1178,6 +1180,7 @@ def __init__(self, session):
11781180
".filesystems",
11791181
".interfaces",
11801182
".ipranges",
1183+
".ip_addresses",
11811184
".logical_volumes",
11821185
".maas",
11831186
".machines",
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
"""Objects for dnsresourcerecords."""
2+
3+
__all__ = ["DNSResourceRecord", "DNSResourceRecords"]
4+
5+
from . import check, check_optional, Object, ObjectField, ObjectSet, ObjectType
6+
7+
8+
class DNSResourceRecordType(ObjectType):
9+
"""Metaclass for `DNSResourceRecords`."""
10+
11+
async def read(cls):
12+
data = await cls._handler.read()
13+
return cls(map(cls._object, data))
14+
15+
16+
class DNSResourceRecords(ObjectSet, metaclass=DNSResourceRecordType):
17+
"""The set of dnsresourcerecords stored in MAAS."""
18+
19+
20+
class DNSResourceRecordType(ObjectType):
21+
async def read(cls, id):
22+
data = await cls._handler.read(id=id)
23+
return cls(data)
24+
25+
26+
class DNSResourceRecord(Object, metaclass=DNSResourceRecordType):
27+
"""A dnsresourcerecord stored in MAAS."""
28+
29+
id = ObjectField.Checked("id", check(int), readonly=True, pk=True)
30+
ttl = ObjectField.Checked("ttl", check_optional(int), check_optional(int))
31+
rrtype = ObjectField.Checked("rrtype", check(str), check(str))
32+
rrdata = ObjectField.Checked("rrdata", check(str), check(str))
33+
fqdn = ObjectField.Checked("fqdn", check(str), check(str))
34+
35+
def __repr__(self):
36+
return super(DNSResourceRecord, self).__repr__(
37+
fields={"ttl", "rrtype", "rrdata", "fqdn"}
38+
)
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
"""Objects for dnsresources."""
2+
3+
__all__ = ["DNSResource", "DNSResources"]
4+
5+
from . import (
6+
check,
7+
check_optional,
8+
Object,
9+
ObjectField,
10+
ObjectSet,
11+
ObjectType,
12+
ObjectFieldRelatedSet,
13+
)
14+
15+
16+
class DNSResourceType(ObjectType):
17+
"""Metaclass for `DNSResources`."""
18+
19+
async def read(cls):
20+
data = await cls._handler.read()
21+
return cls(map(cls._object, data))
22+
23+
24+
class DNSResources(ObjectSet, metaclass=DNSResourceType):
25+
"""The set of dnsresources stored in MAAS."""
26+
27+
28+
class DNSResourceType(ObjectType):
29+
async def read(cls, id):
30+
data = await cls._handler.read(id=id)
31+
return cls(data)
32+
33+
34+
class DNSResource(Object, metaclass=DNSResourceType):
35+
"""A dnsresource stored in MAAS."""
36+
37+
id = ObjectField.Checked("id", check(int), readonly=True, pk=True)
38+
address_ttl = ObjectField.Checked(
39+
"address_ttl", check_optional(int), check_optional(int)
40+
)
41+
fqdn = ObjectField.Checked("fqdn", check(str), check(str))
42+
ip_addresses = ObjectFieldRelatedSet("ip_addresses", "IPAddresses")
43+
resource_records = ObjectFieldRelatedSet("resource_records", "DNSResourceRecords")
44+
45+
def __repr__(self):
46+
return super(DNSResource, self).__repr__(
47+
fields={"address_ttl", "fqdn", "ip_addresses", "resource_records"}
48+
)
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
"""Objects for ipaddresses."""
2+
3+
__all__ = ["IPAddress", "IPAddresses"]
4+
5+
from . import (
6+
check,
7+
parse_timestamp,
8+
Object,
9+
ObjectField,
10+
ObjectSet,
11+
ObjectType,
12+
ObjectFieldRelatedSet,
13+
ObjectFieldRelated,
14+
OriginObjectRef,
15+
)
16+
17+
18+
class IPAddressType(ObjectType):
19+
"""Metaclass for `IPAddresses`."""
20+
21+
async def read(cls):
22+
data = await cls._handler.read()
23+
return cls(map(cls._object, data))
24+
25+
26+
class IPAddresses(ObjectSet, metaclass=IPAddressType):
27+
"""The set of ipaddresses stored in MAAS."""
28+
29+
_object = OriginObjectRef(name="IPAddress")
30+
31+
32+
class IPAddress(Object):
33+
"""An ipaddress stored in MAAS."""
34+
35+
alloc_type = ObjectField.Checked("alloc_type", check(int), check(int))
36+
alloc_type_name = ObjectField.Checked("alloc_type_name", check(str), check(str))
37+
created = ObjectField.Checked("created", parse_timestamp, readonly=True)
38+
ip = ObjectField.Checked("ip", check(str))
39+
owner = ObjectFieldRelated("owner", "User")
40+
interface_set = ObjectFieldRelatedSet("interface_set", "Interfaces")
41+
subnet = ObjectFieldRelated("subnet", "Subnet", readonly=True, default=None)
42+
43+
def __repr__(self):
44+
return super(IPAddress, self).__repr__(
45+
fields={
46+
"alloc_type",
47+
"alloc_type_name",
48+
"created",
49+
"ip",
50+
"owner",
51+
"interface_set",
52+
"subnet",
53+
}
54+
)
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
"""Tests for `maas.client.viscera.dnsresourcerecords`."""
2+
3+
import random
4+
5+
from testtools.matchers import Equals
6+
7+
from .. import dnsresourcerecords
8+
9+
from ..testing import bind
10+
from ...testing import make_string_without_spaces, TestCase
11+
12+
13+
def make_origin():
14+
"""
15+
Create a new origin with DNSResourceRecord and DNSResourceRecords. The former
16+
refers to the latter via the origin, hence why it must be bound.
17+
"""
18+
return bind(
19+
dnsresourcerecords.DNSResourceRecords, dnsresourcerecords.DNSResourceRecord
20+
)
21+
22+
23+
class TestDNSResourceRecords(TestCase):
24+
def test__dnsresourcerecords_read(self):
25+
"""DNSResourceRecords.read() returns a list of DNSResourceRecords."""
26+
DNSResourceRecords = make_origin().DNSResourceRecords
27+
dnsresourcerecords = [
28+
{"id": random.randint(0, 100), "fqdn": make_string_without_spaces()}
29+
for _ in range(3)
30+
]
31+
DNSResourceRecords._handler.read.return_value = dnsresourcerecords
32+
dnsresourcerecords = DNSResourceRecords.read()
33+
self.assertThat(len(dnsresourcerecords), Equals(3))
34+
35+
36+
class TestDNSResourceRecord(TestCase):
37+
def test__dnsresourcerecord_read(self):
38+
DNSResourceRecord = make_origin().DNSResourceRecord
39+
dnsresourcerecord = {
40+
"id": random.randint(0, 100),
41+
"fqdn": make_string_without_spaces(),
42+
}
43+
DNSResourceRecord._handler.read.return_value = dnsresourcerecord
44+
self.assertThat(
45+
DNSResourceRecord.read(id=dnsresourcerecord["id"]),
46+
Equals(DNSResourceRecord(dnsresourcerecord)),
47+
)
48+
DNSResourceRecord._handler.read.assert_called_once_with(
49+
id=dnsresourcerecord["id"]
50+
)
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
"""Tests for `maas.client.viscera.dnsresources`."""
2+
3+
import random
4+
5+
from testtools.matchers import Equals
6+
7+
from .. import dnsresources
8+
9+
from ..testing import bind
10+
from ...testing import make_string_without_spaces, TestCase
11+
12+
13+
def make_origin():
14+
"""
15+
Create a new origin with DNSResource and DNSResources. The former
16+
refers to the latter via the origin, hence why it must be bound.
17+
"""
18+
return bind(dnsresources.DNSResources, dnsresources.DNSResource)
19+
20+
21+
class TestDNSResources(TestCase):
22+
def test__dnsresources_read(self):
23+
"""DNSResources.read() returns a list of DNSResources."""
24+
DNSResources = make_origin().DNSResources
25+
dnsresources = [
26+
{"id": random.randint(0, 100), "fqdn": make_string_without_spaces()}
27+
for _ in range(3)
28+
]
29+
DNSResources._handler.read.return_value = dnsresources
30+
dnsresources = DNSResources.read()
31+
self.assertThat(len(dnsresources), Equals(3))
32+
33+
34+
class TestDNSResource(TestCase):
35+
def test__dnsresource_read(self):
36+
DNSResource = make_origin().DNSResource
37+
dnsresource = {
38+
"id": random.randint(0, 100),
39+
"fqdn": make_string_without_spaces(),
40+
}
41+
DNSResource._handler.read.return_value = dnsresource
42+
self.assertThat(
43+
DNSResource.read(id=dnsresource["id"]), Equals(DNSResource(dnsresource))
44+
)
45+
DNSResource._handler.read.assert_called_once_with(id=dnsresource["id"])
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
"""Tests for `maas.client.viscera.ip_addresses`."""
2+
3+
from testtools.matchers import Equals
4+
5+
from .. import ip_addresses
6+
7+
from ..testing import bind
8+
from ...testing import TestCase
9+
10+
11+
def make_origin():
12+
"""
13+
Create a new origin with IPAddress and IPAddresses. The former
14+
refers to the latter via the origin, hence why it must be bound.
15+
"""
16+
return bind(ip_addresses.IPAddresses, ip_addresses.IPAddress)
17+
18+
19+
class TestIPAddresses(TestCase):
20+
def test__ip_addresses_read(self):
21+
"""IPAddresses.read() returns a list of IPAddresses."""
22+
IPAddresses = make_origin().IPAddresses
23+
ip_addresses = [
24+
{"ip": "10.0.0.%s" % (i + 1), "alloc_type_name": "User reserved"}
25+
for i in range(3)
26+
]
27+
IPAddresses._handler.read.return_value = ip_addresses
28+
ip_addresses = IPAddresses.read()
29+
self.assertThat(len(ip_addresses), Equals(3))

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ def read(filename):
6767
"setuptools",
6868
"testscenarios",
6969
"testtools",
70-
"Twisted",
70+
"Twisted<23.0.0",
7171
],
7272
description="A client API library specially for MAAS.",
7373
long_description=read('README'),

0 commit comments

Comments
 (0)