mirror of
https://github.com/github/octodns.git
synced 2024-05-11 05:55:00 +00:00
252 lines
8.1 KiB
Python
252 lines
8.1 KiB
Python
#
|
|
#
|
|
#
|
|
|
|
from __future__ import (
|
|
absolute_import,
|
|
division,
|
|
print_function,
|
|
unicode_literals,
|
|
)
|
|
|
|
from mock import Mock, call
|
|
from os.path import dirname, join
|
|
from requests_mock import ANY, mock as requests_mock
|
|
from six import text_type
|
|
from unittest import TestCase
|
|
|
|
from octodns.record import Record, Update, Delete
|
|
from octodns.provider.gcore import (
|
|
GCoreProvider,
|
|
GCoreClientBadRequest,
|
|
GCoreClientNotFound,
|
|
GCoreClientException,
|
|
)
|
|
from octodns.provider.yaml import YamlProvider
|
|
from octodns.zone import Zone
|
|
|
|
|
|
class TestGCoreProvider(TestCase):
|
|
expected = Zone("unit.tests.", [])
|
|
source = YamlProvider("test", join(dirname(__file__), "config"))
|
|
source.populate(expected)
|
|
|
|
def test_populate(self):
|
|
|
|
provider = GCoreProvider("test_id", "token")
|
|
|
|
# 400 - Bad Request.
|
|
with requests_mock() as mock:
|
|
mock.get(ANY, status_code=400, text='{"error":"bad body"}')
|
|
|
|
with self.assertRaises(GCoreClientBadRequest) as ctx:
|
|
zone = Zone("unit.tests.", [])
|
|
provider.populate(zone)
|
|
self.assertIn('"error":"bad body"', text_type(ctx.exception))
|
|
|
|
# 404 - Not Found.
|
|
with requests_mock() as mock:
|
|
mock.get(
|
|
ANY, status_code=404, text='{"error":"zone is not found"}'
|
|
)
|
|
|
|
with self.assertRaises(GCoreClientNotFound) as ctx:
|
|
zone = Zone("unit.tests.", [])
|
|
provider._client.zone(zone)
|
|
self.assertIn(
|
|
'"error":"zone is not found"', text_type(ctx.exception)
|
|
)
|
|
|
|
# General error
|
|
with requests_mock() as mock:
|
|
mock.get(ANY, status_code=500, text="Things caught fire")
|
|
|
|
with self.assertRaises(GCoreClientException) as ctx:
|
|
zone = Zone("unit.tests.", [])
|
|
provider.populate(zone)
|
|
self.assertEquals("Things caught fire", text_type(ctx.exception))
|
|
|
|
# No diffs == no changes
|
|
with requests_mock() as mock:
|
|
base = "https://dnsapi.gcorelabs.com/v2/zones/unit.tests/rrsets"
|
|
with open("tests/fixtures/gcore-no-changes.json") as fh:
|
|
mock.get(base, text=fh.read())
|
|
|
|
zone = Zone("unit.tests.", [])
|
|
provider.populate(zone)
|
|
self.assertEquals(4, len(zone.records))
|
|
changes = self.expected.changes(zone, provider)
|
|
self.assertEquals(0, len(changes))
|
|
|
|
# 3 removed + 1 modified
|
|
with requests_mock() as mock:
|
|
base = "https://dnsapi.gcorelabs.com/v2/zones/unit.tests/rrsets"
|
|
with open("tests/fixtures/gcore-records.json") as fh:
|
|
mock.get(base, text=fh.read())
|
|
|
|
zone = Zone("unit.tests.", [])
|
|
provider.populate(zone)
|
|
self.assertEquals(1, len(zone.records))
|
|
changes = self.expected.changes(zone, provider)
|
|
self.assertEquals(4, len(changes))
|
|
self.assertEquals(
|
|
3, len([c for c in changes if isinstance(c, Delete)])
|
|
)
|
|
self.assertEquals(
|
|
1, len([c for c in changes if isinstance(c, Update)])
|
|
)
|
|
|
|
def test_apply(self):
|
|
provider = GCoreProvider("test_id", "token")
|
|
|
|
# Zone does not exists but can be created.
|
|
with requests_mock() as mock:
|
|
mock.get(
|
|
ANY, status_code=404, text='{"error":"zone is not found"}'
|
|
)
|
|
mock.post(ANY, status_code=200, text='{"id":1234}')
|
|
|
|
plan = provider.plan(self.expected)
|
|
provider.apply(plan)
|
|
|
|
# Zone does not exists and can't be created.
|
|
with requests_mock() as mock:
|
|
mock.get(
|
|
ANY, status_code=404, text='{"error":"zone is not found"}'
|
|
)
|
|
mock.post(
|
|
ANY,
|
|
status_code=400,
|
|
text='{"error":"parent zone is already'
|
|
' occupied by another client"}',
|
|
)
|
|
|
|
with self.assertRaises(
|
|
(GCoreClientNotFound, GCoreClientBadRequest)
|
|
) as ctx:
|
|
plan = provider.plan(self.expected)
|
|
provider.apply(plan)
|
|
self.assertIn(
|
|
"parent zone is already occupied by another client",
|
|
text_type(ctx.exception),
|
|
)
|
|
|
|
resp = Mock()
|
|
resp.json = Mock()
|
|
provider._client._request = Mock(return_value=resp)
|
|
|
|
with open("tests/fixtures/gcore-zone.json") as fh:
|
|
zone = fh.read()
|
|
|
|
# non-existent domain
|
|
resp.json.side_effect = [
|
|
GCoreClientNotFound(resp), # no zone in populate
|
|
GCoreClientNotFound(resp), # no domain during apply
|
|
zone,
|
|
]
|
|
plan = provider.plan(self.expected)
|
|
|
|
# create all
|
|
self.assertEquals(4, len(plan.changes))
|
|
self.assertEquals(4, provider.apply(plan))
|
|
self.assertFalse(plan.exists)
|
|
|
|
provider._client._request.assert_has_calls(
|
|
[
|
|
call("GET", "/zones/unit.tests/rrsets"),
|
|
call("GET", "/zones/unit.tests"),
|
|
call("POST", "/zones", data={"name": "unit.tests"}),
|
|
call(
|
|
"POST",
|
|
"/zones/unit.tests/www.sub.unit.tests./A",
|
|
data={
|
|
"ttl": 300,
|
|
"resource_records": [{"content": ["2.2.3.6"]}],
|
|
},
|
|
),
|
|
call(
|
|
"POST",
|
|
"/zones/unit.tests/www.unit.tests./A",
|
|
data={
|
|
"ttl": 300,
|
|
"resource_records": [{"content": ["2.2.3.6"]}],
|
|
},
|
|
),
|
|
call(
|
|
"POST",
|
|
"/zones/unit.tests/aaaa.unit.tests./AAAA",
|
|
data={
|
|
"ttl": 600,
|
|
"resource_records": [
|
|
{
|
|
"content": [
|
|
"2601:644:500:e210:62f8:1dff:feb8:947a"
|
|
]
|
|
}
|
|
],
|
|
},
|
|
),
|
|
call(
|
|
"POST",
|
|
"/zones/unit.tests/unit.tests./A",
|
|
data={
|
|
"ttl": 300,
|
|
"resource_records": [
|
|
{"content": ["1.2.3.4", "1.2.3.5"]}
|
|
],
|
|
},
|
|
),
|
|
]
|
|
)
|
|
# expected number of total calls
|
|
self.assertEquals(7, provider._client._request.call_count)
|
|
|
|
provider._client._request.reset_mock()
|
|
|
|
# delete 1 and update 1
|
|
provider._client.zone_records = Mock(
|
|
return_value=[
|
|
{
|
|
"name": "www",
|
|
"ttl": 300,
|
|
"type": "A",
|
|
"resource_records": [{"content": ["1.2.3.4"]}],
|
|
},
|
|
{
|
|
"name": "ttl",
|
|
"ttl": 600,
|
|
"type": "A",
|
|
"resource_records": [{"content": ["3.2.3.4"]}],
|
|
},
|
|
]
|
|
)
|
|
|
|
# Domain exists, we don't care about return
|
|
resp.json.side_effect = ["{}"]
|
|
|
|
wanted = Zone("unit.tests.", [])
|
|
wanted.add_record(
|
|
Record.new(
|
|
wanted, "ttl", {"ttl": 300, "type": "A", "value": "3.2.3.4"}
|
|
)
|
|
)
|
|
|
|
plan = provider.plan(wanted)
|
|
self.assertTrue(plan.exists)
|
|
self.assertEquals(2, len(plan.changes))
|
|
self.assertEquals(2, provider.apply(plan))
|
|
|
|
provider._client._request.assert_has_calls(
|
|
[
|
|
call("DELETE", "/zones/unit.tests/www.unit.tests./A"),
|
|
call(
|
|
"PUT",
|
|
"/zones/unit.tests/ttl.unit.tests./A",
|
|
data={
|
|
"ttl": 300,
|
|
"resource_records": [{"content": ["3.2.3.4"]}],
|
|
},
|
|
),
|
|
]
|
|
)
|