Merge ~newell-jensen/maas:2.6-lp1804563 into maas:2.6

Proposed by Newell Jensen
Status: Merged
Approved by: Newell Jensen
Approved revision: 8bffa14de94686ffedc5ea63e858ad709925ca0f
Merge reported by: MAAS Lander
Merged at revision: not available
Proposed branch: ~newell-jensen/maas:2.6-lp1804563
Merge into: maas:2.6
Diff against target: 176 lines (+134/-5)
2 files modified
src/maasserver/api/dnsresources.py (+36/-4)
src/maasserver/api/tests/test_dnsresources.py (+98/-1)
Reviewer Review Type Date Requested Status
Newell Jensen (community) Approve
Review via email: mp+368160@code.launchpad.net

Commit message

backport of b65d218f01be698e858c27aae2d9b4f11291fc00

LP: #1804563 -- Modify dnsresource update API endpoint to take same parameters that dnsresources create API endpoint uses.

To post a comment you must log in.
Revision history for this message
Newell Jensen (newell-jensen) wrote :

Self reviewed backport

review: Approve
Revision history for this message
MAAS Lander (maas-lander) wrote :

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/src/maasserver/api/dnsresources.py b/src/maasserver/api/dnsresources.py
2index 1386d7a..81ba2a5 100644
3--- a/src/maasserver/api/dnsresources.py
4+++ b/src/maasserver/api/dnsresources.py
5@@ -289,10 +289,20 @@ class DNSResourceHandler(OperationsHandler):
6 @param (int) "{id}" [required=true] The DNS resource id.
7
8 @param (string) "fqdn" [required=false] Hostname (with domain) for the
9- dnsresource.
10+ dnsresource. Either ``fqdn`` or ``name`` and ``domain`` must be
11+ specified. ``fqdn`` is ignored if either ``name`` or ``domain`` is
12+ given.
13
14- @param (string) "ip_address" [required=false] Address to assign to the
15- dnsresource.
16+ @param (string) "name" [required=false] Hostname (without domain).
17+
18+ @param (string) "domain" [required=false] Domain (name or id).
19+
20+ @param (string) "address_ttl" [required=false] Default TTL for entries
21+ in this zone.
22+
23+ @param (string) "ip_addresses" [required=false] Address (ip or id) to
24+ assign to the dnsresource. This creates an A or AAAA record,
25+ for each of the supplied ip_addresses, IPv4 or IPv6, respectively.
26
27 @success (http-status-code) "server-success" 200
28 @success (json) "success-json" A JSON object containing the updated DNS
29@@ -309,10 +319,32 @@ class DNSResourceHandler(OperationsHandler):
30 @error-example "not-found"
31 Not Found
32 """
33+ data = request.data.copy()
34+ fqdn = data.get('fqdn', None)
35+ name = data.get('name', None)
36+ domainname = data.get('domain', None)
37+ # If the user gave us fqdn and did not give us name/domain, expand
38+ # fqdn.
39+ if domainname is None and name is None and fqdn is not None:
40+ # Assume that we're working with an address, since we ignore
41+ # rrtype and rrdata.
42+ (name, domainname) = separate_fqdn(fqdn, 'A')
43+ data['domain'] = domainname
44+ data['name'] = name
45+ # If the domain is a name, make it an id.
46+ if domainname is not None:
47+ if domainname.isdigit():
48+ domain = Domain.objects.get_domain_or_404(
49+ domainname, user=request.user, perm=NodePermission.view)
50+ else:
51+ domain = Domain.objects.get_domain_or_404(
52+ "name:%s" % domainname, user=request.user,
53+ perm=NodePermission.view)
54+ data['domain'] = domain.id
55 dnsresource = DNSResource.objects.get_dnsresource_or_404(
56 id, request.user, NodePermission.admin)
57 form = DNSResourceForm(
58- instance=dnsresource, data=request.data, request=request)
59+ instance=dnsresource, data=data, request=request)
60 if form.is_valid():
61 return form.save()
62 else:
63diff --git a/src/maasserver/api/tests/test_dnsresources.py b/src/maasserver/api/tests/test_dnsresources.py
64index 6c92513..0025a42 100644
65--- a/src/maasserver/api/tests/test_dnsresources.py
66+++ b/src/maasserver/api/tests/test_dnsresources.py
67@@ -1,4 +1,4 @@
68-# Copyright 2016 Canonical Ltd. This software is licensed under the
69+# Copyright 2016-2019 Canonical Ltd. This software is licensed under the
70 # GNU Affero General Public License version 3 (see the file LICENSE).
71
72 """Tests for DNSResource API."""
73@@ -349,6 +349,103 @@ class TestDNSResourceAPI(APITestCase.ForUser):
74 self.assertEqual(
75 http.client.FORBIDDEN, response.status_code, response.content)
76
77+ def test_update_by_name_domain__id(self):
78+ self.become_admin()
79+ dnsresource = factory.make_DNSResource()
80+ new_name = factory.make_name("dnsresource")
81+ domain = factory.make_Domain()
82+ fqdn = "%s.%s" % (new_name, domain.name)
83+ sip = factory.make_StaticIPAddress()
84+ uri = get_dnsresource_uri(dnsresource)
85+ response = self.client.put(uri, {
86+ "name": new_name,
87+ "domain": domain.id,
88+ "ip_addresses": str(sip.ip),
89+ })
90+ self.assertEqual(
91+ http.client.OK, response.status_code, response.content)
92+ self.assertEqual(
93+ fqdn,
94+ json.loads(
95+ response.content.decode(settings.DEFAULT_CHARSET))['fqdn'])
96+ self.assertEqual(
97+ sip.ip,
98+ json.loads(
99+ response.content.decode(
100+ settings.DEFAULT_CHARSET))['ip_addresses'][0]['ip'])
101+
102+ def test_update_by_name_domain__name(self):
103+ self.become_admin()
104+ dnsresource = factory.make_DNSResource()
105+ new_name = factory.make_name("dnsresource")
106+ domain = factory.make_Domain()
107+ fqdn = "%s.%s" % (new_name, domain.name)
108+ sip = factory.make_StaticIPAddress()
109+ uri = get_dnsresource_uri(dnsresource)
110+ response = self.client.put(uri, {
111+ "name": new_name,
112+ "domain": domain.name,
113+ "ip_addresses": str(sip.ip),
114+ })
115+ self.assertEqual(
116+ http.client.OK, response.status_code, response.content)
117+ self.assertEqual(
118+ fqdn,
119+ json.loads(
120+ response.content.decode(settings.DEFAULT_CHARSET))['fqdn'])
121+ self.assertEqual(
122+ sip.ip,
123+ json.loads(
124+ response.content.decode(
125+ settings.DEFAULT_CHARSET))['ip_addresses'][0]['ip'])
126+
127+ def test_update_by_fqdn(self):
128+ self.become_admin()
129+ dnsresource = factory.make_DNSResource()
130+ new_name = factory.make_name("dnsresource")
131+ domain = factory.make_Domain()
132+ fqdn = "%s.%s" % (new_name, domain.name)
133+ sip = factory.make_StaticIPAddress()
134+ uri = get_dnsresource_uri(dnsresource)
135+ response = self.client.put(uri, {
136+ "fqdn": fqdn,
137+ "ip_addresses": str(sip.ip),
138+ })
139+ self.assertEqual(
140+ http.client.OK, response.status_code, response.content)
141+ self.assertEqual(
142+ fqdn,
143+ json.loads(
144+ response.content.decode(settings.DEFAULT_CHARSET))['fqdn'])
145+ self.assertEqual(
146+ sip.ip,
147+ json.loads(
148+ response.content.decode(
149+ settings.DEFAULT_CHARSET))['ip_addresses'][0]['ip'])
150+
151+ def test_update_multiple_ips(self):
152+ self.become_admin()
153+ dnsresource = factory.make_DNSResource()
154+ new_name = factory.make_name("dnsresource")
155+ domain = factory.make_Domain()
156+ fqdn = "%s.%s" % (new_name, domain.name)
157+ ips = [factory.make_StaticIPAddress() for _ in range(2)]
158+ uri = get_dnsresource_uri(dnsresource)
159+ response = self.client.put(uri, {
160+ "name": new_name,
161+ "domain": domain.id,
162+ "ip_addresses": " ".join([str(ip.ip) for ip in ips]),
163+ })
164+ self.assertEqual(
165+ http.client.OK, response.status_code, response.content)
166+ self.assertEqual(
167+ fqdn,
168+ json.loads(
169+ response.content.decode(settings.DEFAULT_CHARSET))['fqdn'])
170+ result = json.loads(response.content.decode(
171+ settings.DEFAULT_CHARSET))['ip_addresses']
172+ self.assertEqual([ip.ip for ip in ips], [ip['ip'] for ip in result])
173+
174 def test_delete_deletes_dnsresource(self):
175 self.become_admin()
176 dnsresource = factory.make_DNSResource()

Subscribers

People subscribed via source and target branches