2026-03-10 20:30:54 -04:00
|
|
|
import json
|
|
|
|
|
from unittest.mock import patch
|
|
|
|
|
|
|
|
|
|
from django.test import TestCase
|
|
|
|
|
|
|
|
|
|
from api_v2.models import ApiKey
|
|
|
|
|
from dns.models import DNSSettings, StaticHost
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class ApiV2ManageDnsRecordTests(TestCase):
|
|
|
|
|
def setUp(self):
|
|
|
|
|
self.api_key = ApiKey.objects.create(name="dns-test-key", enabled=True)
|
|
|
|
|
self.url = "/api/v2/manage_dns_record/"
|
|
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
|
def _fake_export_dns_configuration():
|
|
|
|
|
dns_settings, dns_settings_created = DNSSettings.objects.get_or_create(name="dns_settings")
|
|
|
|
|
dns_settings.pending_changes = False
|
|
|
|
|
dns_settings.save(update_fields=["pending_changes", "updated"])
|
|
|
|
|
|
|
|
|
|
@patch("api_v2.views_api.export_dns_configuration")
|
|
|
|
|
def test_post_creates_record(self, mock_export):
|
|
|
|
|
response = self.client.post(
|
|
|
|
|
self.url,
|
|
|
|
|
data=json.dumps({
|
|
|
|
|
"hostname": "App.Example.com",
|
|
|
|
|
"ip_address": "10.20.30.40",
|
|
|
|
|
"skip_reload": True,
|
|
|
|
|
}),
|
|
|
|
|
content_type="application/json",
|
|
|
|
|
HTTP_TOKEN=str(self.api_key.token),
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
self.assertEqual(response.status_code, 201)
|
|
|
|
|
body = response.json()
|
|
|
|
|
self.assertEqual(body["hostname"], "app.example.com")
|
|
|
|
|
self.assertEqual(body["ip_address"], "10.20.30.40")
|
|
|
|
|
mock_export.assert_not_called()
|
|
|
|
|
self.assertTrue(StaticHost.objects.filter(hostname="app.example.com").exists())
|
|
|
|
|
|
|
|
|
|
@patch("api_v2.views_api.export_dns_configuration")
|
|
|
|
|
def test_post_fails_if_record_exists(self, mock_export):
|
|
|
|
|
StaticHost.objects.create(hostname="app.example.com", ip_address="10.20.30.40")
|
|
|
|
|
|
|
|
|
|
response = self.client.post(
|
|
|
|
|
self.url,
|
|
|
|
|
data=json.dumps({
|
|
|
|
|
"hostname": "app.example.com",
|
|
|
|
|
"ip_address": "10.20.30.99",
|
|
|
|
|
"skip_reload": False,
|
|
|
|
|
}),
|
|
|
|
|
content_type="application/json",
|
|
|
|
|
HTTP_TOKEN=str(self.api_key.token),
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
self.assertEqual(response.status_code, 400)
|
|
|
|
|
self.assertIn("already exists", response.json()["error_message"])
|
|
|
|
|
self.assertEqual(str(StaticHost.objects.get(hostname="app.example.com").ip_address), "10.20.30.40")
|
|
|
|
|
mock_export.assert_not_called()
|
|
|
|
|
|
|
|
|
|
@patch("api_v2.views_api.export_dns_configuration")
|
|
|
|
|
def test_put_upserts_existing_record(self, mock_export):
|
|
|
|
|
mock_export.side_effect = self._fake_export_dns_configuration
|
|
|
|
|
StaticHost.objects.create(hostname="app.example.com", ip_address="10.20.30.40")
|
|
|
|
|
DNSSettings.objects.create(name="dns_settings", pending_changes=True)
|
|
|
|
|
|
|
|
|
|
response = self.client.put(
|
|
|
|
|
self.url,
|
|
|
|
|
data=json.dumps({
|
|
|
|
|
"hostname": "app.example.com",
|
|
|
|
|
"ip_address": "10.20.30.41",
|
|
|
|
|
"skip_reload": False,
|
|
|
|
|
}),
|
|
|
|
|
content_type="application/json",
|
|
|
|
|
HTTP_TOKEN=str(self.api_key.token),
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
self.assertEqual(response.status_code, 200)
|
|
|
|
|
self.assertEqual(str(StaticHost.objects.get(hostname="app.example.com").ip_address), "10.20.30.41")
|
|
|
|
|
self.assertEqual(StaticHost.objects.filter(hostname="app.example.com").count(), 1)
|
|
|
|
|
self.assertFalse(DNSSettings.objects.get(name="dns_settings").pending_changes)
|
|
|
|
|
mock_export.assert_called_once()
|
|
|
|
|
|
|
|
|
|
@patch("api_v2.views_api.export_dns_configuration")
|
|
|
|
|
def test_put_upserts_missing_record_as_create(self, mock_export):
|
|
|
|
|
mock_export.side_effect = self._fake_export_dns_configuration
|
|
|
|
|
|
|
|
|
|
response = self.client.put(
|
|
|
|
|
self.url,
|
|
|
|
|
data=json.dumps({
|
|
|
|
|
"hostname": "new.example.com",
|
|
|
|
|
"ip_address": "10.20.30.50",
|
|
|
|
|
"skip_reload": False,
|
|
|
|
|
}),
|
|
|
|
|
content_type="application/json",
|
|
|
|
|
HTTP_TOKEN=str(self.api_key.token),
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
self.assertEqual(response.status_code, 201)
|
|
|
|
|
self.assertTrue(StaticHost.objects.filter(hostname="new.example.com").exists())
|
|
|
|
|
mock_export.assert_called_once()
|
|
|
|
|
|
|
|
|
|
@patch("api_v2.views_api.export_dns_configuration")
|
|
|
|
|
def test_delete_deletes_record_and_does_not_require_ip(self, mock_export):
|
|
|
|
|
StaticHost.objects.create(hostname="del.example.com", ip_address="10.1.2.3")
|
|
|
|
|
|
|
|
|
|
response = self.client.delete(
|
|
|
|
|
self.url,
|
|
|
|
|
data=json.dumps({
|
|
|
|
|
"hostname": "del.example.com",
|
|
|
|
|
"skip_reload": True,
|
|
|
|
|
}),
|
|
|
|
|
content_type="application/json",
|
|
|
|
|
HTTP_TOKEN=str(self.api_key.token),
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
self.assertEqual(response.status_code, 200)
|
|
|
|
|
self.assertFalse(StaticHost.objects.filter(hostname="del.example.com").exists())
|
|
|
|
|
mock_export.assert_not_called()
|