def create(self, request): """Create a dnsresourcerecord. :param fqdn: Hostname (with domain) for the dnsresource. Either fqdn or (name, domain) must be specified. Fqdn is ignored if either name or domain is given. :param name: Hostname (without domain) :param domain: Domain (name or id) :param rrtype: resource type to create :param rrdata: resource data (everything to the right of resource type.) """ data = request.data.copy() domain = None fqdn = data.get('fqdn', None) name = data.get('name', None) domainname = data.get('domain', None) rrtype = data.get('rrtype', None) rrdata = data.get('rrdata', None) if rrtype is None: raise MAASAPIBadRequest("rrtype must be provided.") if rrdata is None: raise MAASAPIBadRequest("rrdata must be provided.") # If the user gave us fqdn and did not give us name/domain, expand # fqdn. if domainname is None and name is None and fqdn is not None: # We need a type for resource separation. If the user didn't give # us a rrtype, then assume it's an address of some sort. rrtype = data.get('rrtype', None) (name, domainname) = separate_fqdn(fqdn, rrtype) data['domain'] = domainname data['name'] = name # If the domain is a name, make it an id. if domainname is not None: if domainname.isdigit(): domain = Domain.objects.get_domain_or_404( domainname, user=request.user, perm=NODE_PERMISSION.VIEW) else: domain = Domain.objects.get_domain_or_404( "name:%s" % domainname, user=request.user, perm=NODE_PERMISSION.VIEW) data['domain'] = domain.id if domain is None or name is None: raise MAASAPIValidationError( "Either name and domain (or fqdn) must be specified") # Do we already have a DNSResource for this fqdn? dnsrr = DNSResource.objects.filter(name=name, domain__id=domain.id) if not dnsrr.exists(): form = DNSResourceForm(data=data, request=request) if form.is_valid(): form.save() else: raise MAASAPIValidationError(form.errors) dnsrr = DNSResource.objects.filter(name=name, domain__id=domain.id) data['dnsresource'] = dnsrr form = DNSDataForm(data=data) if form.is_valid(): return form.save() else: raise MAASAPIValidationError(form.errors)
def create_dnsresource(self, params): self._get_domain_or_permission_error(params) form = DNSResourceForm(data=params, user=self.user) if form.is_valid(): form.save() else: raise ValidationError(form.errors)
def update_dnsresource(self, params): domain = self._get_domain_or_permission_error(params) dnsresource = DNSResource.objects.get(domain=domain, id=params['dnsresource_id']) form = DNSResourceForm(instance=dnsresource, data=params, user=self.user) if form.is_valid(): form.save() else: raise ValidationError return self.full_dehydrate(domain)
def delete_address_record(self, params): domain = self._get_domain_or_permission_error(params) dnsresource = DNSResource.objects.get(domain=domain, id=params['dnsresource_id']) ip_addresses = dnsresource.get_addresses() ip_addresses.remove(params['rrdata']) params['ip_addresses'] = ' '.join(ip_addresses) form = DNSResourceForm(data=params, user=self.user, instance=dnsresource) if form.is_valid(): form.save() else: raise ValidationError(form.errors)
def create_address_record(self, params): domain = self._get_domain_or_permission_error(params) dnsresource, created = DNSResource.objects.get_or_create( domain=domain, name=params['name']) if created: ip_addresses = [] else: ip_addresses = dnsresource.get_addresses() ip_addresses.extend(params['ip_addresses']) params['ip_addresses'] = ' '.join(ip_addresses) form = DNSResourceForm(data=params, user=self.user, instance=dnsresource) if form.is_valid(): form.save() else: raise ValidationError(form.errors)
def test__update_allows_multiple_ips(self): dnsresource = factory.make_DNSResource() new_name = factory.make_name("new") new_sip_ids = [factory.make_StaticIPAddress().id for _ in range(3)] form = DNSResourceForm(instance=dnsresource, data={ "name": new_name, "ip_addresses": " ".join(str(id) for id in new_sip_ids), }) self.assertTrue(form.is_valid(), form.errors) form.save() self.assertEqual(new_name, reload_object(dnsresource).name) self.assertItemsEqual( new_sip_ids, [ip.id for ip in reload_object(dnsresource).ip_addresses.all()])
def test_does_not_require_ip_addresses(self): name = factory.make_name("dnsresource") domain = factory.make_Domain() form = DNSResourceForm({"name": name, "domain": domain.id}) self.assertTrue(form.is_valid(), form.errors) dnsresource = form.save() self.assertEqual(name, dnsresource.name) self.assertEqual(domain.id, dnsresource.domain.id)
def test_accepts_address_ttl_equals_none(self): name = factory.make_name("dnsresource") domain = factory.make_Domain() ttl = random.randint(1, 1000) form = DNSResourceForm({ "name": name, "domain": domain.id, "address_ttl": ttl }) self.assertTrue(form.is_valid(), form.errors) dnsresource = form.save() form = DNSResourceForm(instance=dnsresource, data={"address_ttl": None}) self.assertTrue(form.is_valid(), form.errors) dnsresource = form.save() self.assertEqual(name, dnsresource.name) self.assertEqual(domain.id, dnsresource.domain.id) self.assertEqual(None, dnsresource.address_ttl)
def test__updates_dnsresource(self): dnsresource = factory.make_DNSResource() new_name = factory.make_name("new") new_sip_ids = [factory.make_StaticIPAddress().id] new_ttl = random.randint(1, 1000) form = DNSResourceForm(instance=dnsresource, data={ "name": new_name, "ip_addresses": new_sip_ids, "address_ttl": new_ttl, }) self.assertTrue(form.is_valid(), form.errors) form.save() self.assertEqual(new_name, reload_object(dnsresource).name) self.assertEqual(new_ttl, reload_object(dnsresource).address_ttl) self.assertItemsEqual( new_sip_ids, [ip.id for ip in reload_object(dnsresource).ip_addresses.all()])
def create(self, request): """@description-title Create a DNS resource @description Create a DNS resource. @param (string) "fqdn" [required=false] Hostname (with domain) for the dnsresource. Either ``fqdn`` or ``name`` and ``domain`` must be specified. ``fqdn`` is ignored if either ``name`` or ``domain`` is given. @param (string) "name" [required=true] Hostname (without domain). @param (string) "domain" [required=true] Domain (name or id). @param (string) "address_ttl" [required=false] Default TTL for entries in this zone. @param (string) "ip_addresses" [required=false] Address (ip or id) to assign to the dnsresource. This creates an A or AAAA record, for each of the supplied ip_addresses, IPv4 or IPv6, respectively. @success (http-status-code) "server-success" 200 @success (json) "success-json" A JSON object containing the new DNS resource object. @success-example "success-json" [exkey=dnsresources-create] placeholder text """ data = request.data.copy() fqdn = data.get("fqdn", None) name = data.get("name", None) domainname = data.get("domain", None) # If the user gave us fqdn and did not give us name/domain, expand # fqdn. if domainname is None and name is None and fqdn is not None: # Assume that we're working with an address, since we ignore # rrtype and rrdata. (name, domainname) = separate_fqdn(fqdn, "A") data["domain"] = domainname data["name"] = name # If the domain is a name, make it an id. if domainname is not None: if domainname.isdigit(): domain = Domain.objects.get_domain_or_404( domainname, user=request.user, perm=NodePermission.view ) else: domain = Domain.objects.get_domain_or_404( "name:%s" % domainname, user=request.user, perm=NodePermission.view, ) data["domain"] = domain.id form = DNSResourceForm(data=data, request=request) if form.is_valid(): return form.save() else: raise MAASAPIValidationError(form.errors)
def create_address_record(self, params): domain = self._get_domain_or_permission_error(params) if params["ip_addresses"] == [""]: raise ValidationError( "Data field is required when creating an %s record." % params["rrtype"]) dnsresource, created = DNSResource.objects.get_or_create( domain=domain, name=params["name"]) if created: ip_addresses = [] else: ip_addresses = dnsresource.get_addresses() ip_addresses.extend(params["ip_addresses"]) params["ip_addresses"] = " ".join(ip_addresses) form = DNSResourceForm(data=params, user=self.user, instance=dnsresource) if form.is_valid(): form.save() else: raise ValidationError(form.errors)
def update_address_record(self, params): domain = self._get_domain_or_permission_error(params) dnsresource, created = DNSResource.objects.get_or_create( domain=domain, name=params["name"]) if created: # If we ended up creating a record, that's because the name # was changed, so we'll start with an empty list. But that also # means we need to edit the record with the original name. ip_addresses = [] previous_dnsresource = DNSResource.objects.get( domain=domain, name=params["previous_name"]) prevoius_ip_addresses = previous_dnsresource.get_addresses() prevoius_ip_addresses.remove(params["previous_rrdata"]) modified_addresses = " ".join(prevoius_ip_addresses) form = DNSResourceForm( data=dict(ip_addresses=modified_addresses), user=self.user, instance=previous_dnsresource, ) if form.is_valid(): form.save() else: raise ValidationError(form.errors) else: ip_addresses = dnsresource.get_addresses() # Remove the previous address for the record being edited. # The previous_rrdata field will contain the original value # for the IP address in the edited row. ip_addresses.remove(params["previous_rrdata"]) ip_addresses.extend(params["ip_addresses"]) params["ip_addresses"] = " ".join(ip_addresses) form = DNSResourceForm(data=params, user=self.user, instance=dnsresource) if form.is_valid(): form.save() else: raise ValidationError(form.errors)
def test__accepts_string_for_ip_addresses(self): name = factory.make_name("dnsresource") sip = factory.make_StaticIPAddress() domain = factory.make_Domain() form = DNSResourceForm({ "name": name, "domain": domain.id, "ip_addresses": str(sip.id) }) self.assertTrue(form.is_valid(), form.errors) dnsresource = form.save() self.assertEqual(name, dnsresource.name) self.assertEqual(domain.id, dnsresource.domain.id) self.assertEqual(sip.id, dnsresource.ip_addresses.first().id)
def test__accepts_mix_of_id_and_ipaddress(self): name = factory.make_name("dnsresource") domain = factory.make_Domain() ips = [factory.make_StaticIPAddress() for _ in range(6)] in_vals = [ str(ip.id) if factory.pick_bool() else str(ip.ip) for ip in ips ] form = DNSResourceForm({ "name": name, "domain": domain.id, "ip_addresses": " ".join(in_vals), }) self.assertTrue(form.is_valid(), form.errors) dnsresource = form.save() self.assertEqual(name, dnsresource.name) self.assertEqual(domain.id, dnsresource.domain.id) actual = {ip.id for ip in dnsresource.ip_addresses.all()} self.assertItemsEqual(set(ip.id for ip in ips), actual)
def test__creates_dnsresource(self): name = factory.make_name("dnsresource") sip = factory.make_StaticIPAddress() domain = factory.make_Domain() request = Mock() request.user = factory.make_User() form = DNSResourceForm( { "name": name, "domain": domain.id, "ip_addresses": [sip.id], }, request=request) self.assertTrue(form.is_valid(), form.errors) dnsresource = form.save() self.assertEqual(name, dnsresource.name) self.assertEqual(domain.id, dnsresource.domain.id) self.assertEqual(sip.id, dnsresource.ip_addresses.first().id)
def update(self, request, id): """Update dnsresource. :param fqdn: Hostname (with domain) for the dnsresource. :param ip_address: Address to assign to the dnsresource. Returns 403 if the user does not have permission to update the dnsresource. Returns 404 if the dnsresource is not found. """ dnsresource = DNSResource.objects.get_dnsresource_or_404( id, request.user, NODE_PERMISSION.ADMIN) form = DNSResourceForm(instance=dnsresource, data=request.data, request=request) if form.is_valid(): return form.save() else: raise MAASAPIValidationError(form.errors)
def create(self, request): """Create a dnsresource. :param fqdn: Hostname (with domain) for the dnsresource. Either fqdn or (name, domain) must be specified. Fqdn is ignored if either name or domain is given. :param name: Hostname (without domain) :param domain: Domain (name or id) :param address_ttl: Default ttl for entries in this zone. :param ip_addresses: (optional) Address (ip or id) to assign to the dnsresource. """ data = request.data.copy() fqdn = data.get('fqdn', None) name = data.get('name', None) domainname = data.get('domain', None) # If the user gave us fqdn and did not give us name/domain, expand # fqdn. if domainname is None and name is None and fqdn is not None: # Assume that we're working with an address, since we ignore # rrtype and rrdata. (name, domainname) = separate_fqdn(fqdn, 'A') data['domain'] = domainname data['name'] = name # If the domain is a name, make it an id. if domainname is not None: if domainname.isdigit(): domain = Domain.objects.get_domain_or_404( domainname, user=request.user, perm=NODE_PERMISSION.VIEW) else: domain = Domain.objects.get_domain_or_404( "name:%s" % domainname, user=request.user, perm=NODE_PERMISSION.VIEW) data['domain'] = domain.id form = DNSResourceForm(data=data, request=request) if form.is_valid(): return form.save() else: raise MAASAPIValidationError(form.errors)
def test__creates_staticipaddresses(self): name = factory.make_name("dnsresource") domain = factory.make_Domain() ips = [factory.make_ip_address() for _ in range(3)] request = Mock() request.user = factory.make_User() form = DNSResourceForm( { "name": name, "domain": domain.id, "ip_addresses": " ".join(ips), }, request=request) self.assertTrue(form.is_valid(), form.errors) dnsresource = form.save() self.assertEqual(name, dnsresource.name) self.assertEqual(domain.id, dnsresource.domain.id) actual_ips = dnsresource.ip_addresses.all() actual = {str(ip.ip) for ip in actual_ips} self.assertItemsEqual(set(ips), actual) actual_users = {ip.user_id for ip in actual_ips} self.assertItemsEqual({request.user.id}, actual_users)
def create(self, request): """Create a DNS resource record. :param fqdn: Hostname (with domain) for the dnsresource. Either fqdn or (name, domain) must be specified. Fqdn is ignored if either name or domain is given (e.g. www.your-maas.maas). :param name: The name (or hostname without a domain) of the DNS resource record (e.g. www.your-maas) :param domain: The domain (name or id) where to create the DNS resource record (Domain (e.g. 'maas') :param rrtype: The resource record type (e.g 'cname', 'mx', 'ns', 'srv', 'sshfp', 'txt') :param rrdata: The resource record data (e.g. 'your-maas', '10 mail.your-maas.maas') """ data = request.data.copy() domain = None fqdn = data.get('fqdn', None) name = data.get('name', None) domainname = data.get('domain', None) rrtype = data.get('rrtype', None) rrdata = data.get('rrdata', None) if rrtype is None: raise MAASAPIBadRequest("rrtype must be provided.") if rrdata is None: raise MAASAPIBadRequest("rrdata must be provided.") # If the user gave us fqdn and did not give us name/domain, expand # fqdn. if domainname is None and name is None and fqdn is not None: # We need a type for resource separation. If the user didn't give # us a rrtype, then assume it's an address of some sort. rrtype = data.get('rrtype', None) (name, domainname) = separate_fqdn(fqdn, rrtype) data['domain'] = domainname data['name'] = name # If the domain is a name, make it an id. if domainname is not None: if domainname.isdigit(): domain = Domain.objects.get_domain_or_404( domainname, user=request.user, perm=NodePermission.view) else: domain = Domain.objects.get_domain_or_404( "name:%s" % domainname, user=request.user, perm=NodePermission.view) data['domain'] = domain.id if domain is None or name is None: raise MAASAPIValidationError( "Either name and domain (or fqdn) must be specified") # Do we already have a DNSResource for this fqdn? dnsrr = DNSResource.objects.filter(name=name, domain__id=domain.id) if not dnsrr.exists(): form = DNSResourceForm(data=data, request=request) if form.is_valid(): form.save() else: raise MAASAPIValidationError(form.errors) dnsrr = DNSResource.objects.filter(name=name, domain__id=domain.id) data['dnsresource'] = dnsrr form = DNSDataForm(data=data) if form.is_valid(): return form.save() else: raise MAASAPIValidationError(form.errors)
def create(self, request): """@description-title Create a DNS resource record @description Create a new DNS resource record. @param (string) "fqdn" [required=false] Hostname (with domain) for the dnsresource. Either ``fqdn`` or ``name`` and ``domain`` must be specified. ``fqdn`` is ignored if either name or domain is given (e.g. www.your-maas.maas). @param (string) "name" [required=false] The name (or hostname without a domain) of the DNS resource record (e.g. www.your-maas) @param (string) "domain" [required=false] The domain (name or id) where to create the DNS resource record (Domain (e.g. 'maas') @param (string) "rrtype" [required=false] The resource record type (e.g ``cname``, ``mx``, ``ns``, ``srv``, ``sshfp``, ``txt``). @param (string) "rrdata" [required=false] The resource record data (e.g. 'your-maas', '10 mail.your-maas.maas') @success (http-status-code) "server-success" 200 @success (json) "success-json" A JSON object containing the new DNS resource record object. @success-example "success-json" [exkey=dnsresourcerecords-create] placeholder text """ data = request.data.copy() domain = None fqdn = data.get("fqdn", None) name = data.get("name", None) domainname = data.get("domain", None) rrtype = data.get("rrtype", None) rrdata = data.get("rrdata", None) if rrtype is None: raise MAASAPIBadRequest("rrtype must be provided.") if rrdata is None: raise MAASAPIBadRequest("rrdata must be provided.") # If the user gave us fqdn and did not give us name/domain, expand # fqdn. if domainname is None and name is None and fqdn is not None: # We need a type for resource separation. If the user didn't give # us a rrtype, then assume it's an address of some sort. rrtype = data.get("rrtype", None) (name, domainname) = separate_fqdn(fqdn, rrtype) data["domain"] = domainname data["name"] = name # If the domain is a name, make it an id. if domainname is not None: if domainname.isdigit(): domain = Domain.objects.get_domain_or_404( domainname, user=request.user, perm=NodePermission.view ) else: domain = Domain.objects.get_domain_or_404( "name:%s" % domainname, user=request.user, perm=NodePermission.view, ) data["domain"] = domain.id if domain is None or name is None: raise MAASAPIValidationError( "Either name and domain (or fqdn) must be specified" ) # Do we already have a DNSResource for this fqdn? dnsrr = DNSResource.objects.filter(name=name, domain__id=domain.id) if not dnsrr.exists(): form = DNSResourceForm(data=data, request=request) if form.is_valid(): form.save() else: raise MAASAPIValidationError(form.errors) dnsrr = DNSResource.objects.filter(name=name, domain__id=domain.id) data["dnsresource"] = dnsrr form = DNSDataForm(data=data) if form.is_valid(): return form.save() else: raise MAASAPIValidationError(form.errors)