505 lines
16 KiB
Python
505 lines
16 KiB
Python
import json
|
|
import os
|
|
|
|
from unittest import TestCase
|
|
from unittest.mock import call, patch
|
|
from pathlib import Path
|
|
|
|
from click.testing import CliRunner
|
|
from requests import HTTPError
|
|
|
|
from transip_client.cli import DEFAULT_API_URL, run
|
|
|
|
|
|
class RunTestCase(TestCase):
|
|
def setUp(self):
|
|
patcher = patch("transip_client.main.subprocess.check_output")
|
|
self.mocked_dns = patcher.start()
|
|
|
|
patcher = patch("transip_client.main.requests.get")
|
|
self.mocked_get = patcher.start()
|
|
|
|
patcher = patch("transip_client.main.requests.put")
|
|
self.mocked_put = patcher.start()
|
|
|
|
patcher = patch("transip_client.main.requests.Session.send")
|
|
self.mocked_session = patcher.start()
|
|
|
|
self.runner = CliRunner()
|
|
|
|
def test_simple(self):
|
|
self.mocked_dns.return_value = b"111.420\n"
|
|
self.mocked_get.return_value.json.return_value = {
|
|
"dnsEntries": [
|
|
{
|
|
"name": "@",
|
|
"expire": 60,
|
|
"type": "A",
|
|
"content": "111.421",
|
|
}
|
|
],
|
|
"_links": [
|
|
{
|
|
"rel": "self",
|
|
"link": "https://api.transip.nl/v6/domains/foobar.com/dns",
|
|
},
|
|
{
|
|
"rel": "domain",
|
|
"link": "https://api.transip.nl/v6/domains/foobar.com",
|
|
},
|
|
],
|
|
}
|
|
|
|
with self.assertLogs("transip_client.main", level="INFO") as logger:
|
|
result = self.runner.invoke(run, ["foobar.com"], env={"TOKEN": "token"})
|
|
|
|
self.assertEqual(
|
|
logger.output, ["INFO:transip_client.main:Updated domain foobar.com"]
|
|
)
|
|
|
|
self.assertEqual(result.exit_code, 0)
|
|
|
|
self.mocked_get.assert_called_with(
|
|
f"{DEFAULT_API_URL}/domains/foobar.com/dns",
|
|
headers={"Authorization": "Bearer token"},
|
|
)
|
|
|
|
expected_json = json.dumps(
|
|
{
|
|
"dnsEntries": [
|
|
{
|
|
"name": "@",
|
|
"expire": 60,
|
|
"type": "A",
|
|
"content": "111.420",
|
|
}
|
|
]
|
|
}
|
|
)
|
|
|
|
self.mocked_put.assert_called_with(
|
|
f"{DEFAULT_API_URL}/domains/foobar.com/dns",
|
|
data=expected_json,
|
|
headers={"Authorization": "Bearer token"},
|
|
)
|
|
|
|
def test_error_response(self):
|
|
self.mocked_dns.return_value = b"111.420\n"
|
|
self.mocked_get.return_value.raise_for_status.side_effect = HTTPError
|
|
|
|
with self.assertLogs("transip_client.main", level="INFO") as logger:
|
|
result = self.runner.invoke(run, ["foobar.com"], env={"TOKEN": "token"})
|
|
|
|
error_log = logger.output[0]
|
|
|
|
self.assertIn("Failed retrieving information for foobar.com", error_log)
|
|
self.assertEqual(result.exit_code, 0)
|
|
|
|
self.mocked_get.assert_called_with(
|
|
f"{DEFAULT_API_URL}/domains/foobar.com/dns",
|
|
headers={"Authorization": "Bearer token"},
|
|
)
|
|
|
|
self.mocked_put.assert_not_called()
|
|
|
|
def test_matching_ip(self):
|
|
self.mocked_dns.return_value = b"111.420\n"
|
|
self.mocked_get.return_value.json.return_value = {
|
|
"dnsEntries": [
|
|
{
|
|
"name": "@",
|
|
"expire": 60,
|
|
"type": "A",
|
|
"content": "111.420",
|
|
}
|
|
],
|
|
"_links": [
|
|
{
|
|
"rel": "self",
|
|
"link": "https://api.transip.nl/v6/domains/foobar.com/dns",
|
|
},
|
|
{
|
|
"rel": "domain",
|
|
"link": "https://api.transip.nl/v6/domains/foobar.com",
|
|
},
|
|
],
|
|
}
|
|
|
|
result = self.runner.invoke(run, ["foobar.com"], env={"TOKEN": "token"})
|
|
|
|
self.assertEqual(result.exit_code, 0)
|
|
|
|
self.mocked_get.assert_called_with(
|
|
f"{DEFAULT_API_URL}/domains/foobar.com/dns",
|
|
headers={"Authorization": "Bearer token"},
|
|
)
|
|
|
|
self.mocked_put.assert_not_called()
|
|
|
|
def test_readonly(self):
|
|
self.mocked_dns.return_value = b"111.420\n"
|
|
self.mocked_get.return_value.json.return_value = {
|
|
"dnsEntries": [
|
|
{
|
|
"name": "@",
|
|
"expire": 60,
|
|
"type": "A",
|
|
"content": "111.421",
|
|
}
|
|
],
|
|
"_links": [
|
|
{
|
|
"rel": "self",
|
|
"link": "https://api.transip.nl/v6/domains/foobar.com/dns",
|
|
},
|
|
{
|
|
"rel": "domain",
|
|
"link": "https://api.transip.nl/v6/domains/foobar.com",
|
|
},
|
|
],
|
|
}
|
|
|
|
result = self.runner.invoke(
|
|
run, ["foobar.com", "--read-only"], env={"TOKEN": "token"}
|
|
)
|
|
|
|
self.assertEqual(result.exit_code, 0)
|
|
|
|
self.mocked_get.assert_called_with(
|
|
f"{DEFAULT_API_URL}/domains/foobar.com/dns",
|
|
headers={"Authorization": "Bearer token"},
|
|
)
|
|
|
|
self.mocked_put.assert_not_called()
|
|
|
|
def test_different_api_url(self):
|
|
self.mocked_dns.return_value = b"111.420\n"
|
|
self.mocked_get.return_value.json.return_value = {
|
|
"dnsEntries": [
|
|
{
|
|
"name": "@",
|
|
"expire": 60,
|
|
"type": "A",
|
|
"content": "111.421",
|
|
}
|
|
],
|
|
"_links": [
|
|
{
|
|
"rel": "self",
|
|
"link": "https://api.transip.nl/v6/domains/foobar.com/dns",
|
|
},
|
|
{
|
|
"rel": "domain",
|
|
"link": "https://api.transip.nl/v6/domains/foobar.com",
|
|
},
|
|
],
|
|
}
|
|
|
|
with self.assertLogs("transip_client.main", level="INFO") as logger:
|
|
result = self.runner.invoke(
|
|
run,
|
|
["foobar.com", "--api-url", "https://other-provider.com"],
|
|
env={"TOKEN": "token"},
|
|
)
|
|
|
|
self.assertEqual(
|
|
logger.output, ["INFO:transip_client.main:Updated domain foobar.com"]
|
|
)
|
|
|
|
self.assertEqual(result.exit_code, 0)
|
|
|
|
self.mocked_get.assert_called_with(
|
|
f"https://other-provider.com/domains/foobar.com/dns",
|
|
headers={"Authorization": "Bearer token"},
|
|
)
|
|
|
|
expected_json = json.dumps(
|
|
{
|
|
"dnsEntries": [
|
|
{
|
|
"name": "@",
|
|
"expire": 60,
|
|
"type": "A",
|
|
"content": "111.420",
|
|
}
|
|
]
|
|
}
|
|
)
|
|
|
|
self.mocked_put.assert_called_with(
|
|
f"https://other-provider.com/domains/foobar.com/dns",
|
|
data=expected_json,
|
|
headers={"Authorization": "Bearer token"},
|
|
)
|
|
|
|
def test_env_var(self):
|
|
self.mocked_dns.return_value = b"111.420\n"
|
|
self.mocked_get.return_value.json.return_value = {
|
|
"dnsEntries": [
|
|
{
|
|
"name": "@",
|
|
"expire": 60,
|
|
"type": "A",
|
|
"content": "111.421",
|
|
}
|
|
],
|
|
"_links": [
|
|
{
|
|
"rel": "self",
|
|
"link": "https://api.transip.nl/v6/domains/foobar.com/dns",
|
|
},
|
|
{
|
|
"rel": "domain",
|
|
"link": "https://api.transip.nl/v6/domains/foobar.com",
|
|
},
|
|
],
|
|
}
|
|
|
|
with self.assertLogs("transip_client.main", level="INFO") as logger:
|
|
result = self.runner.invoke(
|
|
run,
|
|
["foobar.com"],
|
|
env={
|
|
"TOKEN": "token",
|
|
"API_URL": "https://new-api.com",
|
|
},
|
|
)
|
|
|
|
self.assertEqual(
|
|
logger.output, ["INFO:transip_client.main:Updated domain foobar.com"]
|
|
)
|
|
|
|
self.assertEqual(result.exit_code, 0)
|
|
|
|
self.mocked_get.assert_called_with(
|
|
"https://new-api.com/domains/foobar.com/dns",
|
|
headers={"Authorization": "Bearer token"},
|
|
)
|
|
|
|
expected_json = json.dumps(
|
|
{
|
|
"dnsEntries": [
|
|
{
|
|
"name": "@",
|
|
"expire": 60,
|
|
"type": "A",
|
|
"content": "111.420",
|
|
}
|
|
]
|
|
}
|
|
)
|
|
|
|
self.mocked_put.assert_called_with(
|
|
"https://new-api.com/domains/foobar.com/dns",
|
|
data=expected_json,
|
|
headers={"Authorization": "Bearer token"},
|
|
)
|
|
|
|
def test_multi_arg_env_var(self):
|
|
self.mocked_dns.return_value = b"111.420\n"
|
|
self.mocked_get.return_value.json.side_effect = [
|
|
{
|
|
"dnsEntries": [
|
|
{
|
|
"name": "@",
|
|
"expire": 60,
|
|
"type": "A",
|
|
"content": "111.421",
|
|
}
|
|
],
|
|
"_links": [
|
|
{
|
|
"rel": "self",
|
|
"link": "https://api.transip.nl/v6/domains/foobar.com/dns",
|
|
},
|
|
{
|
|
"rel": "domain",
|
|
"link": "https://api.transip.nl/v6/domains/foobar.com",
|
|
},
|
|
],
|
|
},
|
|
{
|
|
"dnsEntries": [
|
|
{
|
|
"name": "@",
|
|
"expire": 60,
|
|
"type": "A",
|
|
"content": "111.421",
|
|
}
|
|
],
|
|
"_links": [
|
|
{
|
|
"rel": "self",
|
|
"link": "https://api.transip.nl/v6/domains/foofoo.com/dns",
|
|
},
|
|
{
|
|
"rel": "domain",
|
|
"link": "https://api.transip.nl/v6/domains/foofoo.com",
|
|
},
|
|
],
|
|
},
|
|
]
|
|
|
|
with self.assertLogs("transip_client.main", level="INFO") as logger:
|
|
result = self.runner.invoke(
|
|
run, [], env={"TOKEN": "token", "DOMAINS": "foobar.com foofoo.com"}
|
|
)
|
|
|
|
self.assertIsNone(result.exception)
|
|
self.assertEqual(
|
|
logger.output,
|
|
[
|
|
"INFO:transip_client.main:Updated domain foobar.com",
|
|
"INFO:transip_client.main:Updated domain foofoo.com",
|
|
],
|
|
)
|
|
|
|
self.assertEqual(result.exit_code, 0)
|
|
|
|
expected_calls = [
|
|
call(
|
|
f"{DEFAULT_API_URL}/domains/foobar.com/dns",
|
|
headers={"Authorization": "Bearer token"},
|
|
),
|
|
call().raise_for_status(),
|
|
call().json(),
|
|
call(
|
|
f"{DEFAULT_API_URL}/domains/foofoo.com/dns",
|
|
headers={"Authorization": "Bearer token"},
|
|
),
|
|
call().raise_for_status(),
|
|
call().json(),
|
|
]
|
|
|
|
# use any_order because of the asynchronous requests
|
|
self.mocked_get.assert_has_calls(expected_calls, any_order=True)
|
|
|
|
expected_json = json.dumps(
|
|
{
|
|
"dnsEntries": [
|
|
{
|
|
"name": "@",
|
|
"expire": 60,
|
|
"type": "A",
|
|
"content": "111.420",
|
|
}
|
|
]
|
|
}
|
|
)
|
|
|
|
expected_calls = [
|
|
call(
|
|
f"{DEFAULT_API_URL}/domains/foobar.com/dns",
|
|
data=expected_json,
|
|
headers={"Authorization": "Bearer token"},
|
|
),
|
|
call().raise_for_status(),
|
|
call(
|
|
f"{DEFAULT_API_URL}/domains/foofoo.com/dns",
|
|
data=expected_json,
|
|
headers={"Authorization": "Bearer token"},
|
|
),
|
|
call().raise_for_status(),
|
|
]
|
|
|
|
self.mocked_put.assert_has_calls(expected_calls, any_order=True)
|
|
|
|
def test_no_domains(self):
|
|
result = self.runner.invoke(run, [], env={"TOKEN": "token"})
|
|
|
|
self.assertEqual(result.exit_code, 1)
|
|
self.assertEqual(str(result.exception), "No domain(s) specified")
|
|
|
|
self.mocked_get.assert_not_called()
|
|
self.mocked_put.assert_not_called()
|
|
|
|
def test_no_token_or_login_with_private_key_path(self):
|
|
result = self.runner.invoke(run, ["foobar.com"])
|
|
|
|
self.assertEqual(result.exit_code, 1)
|
|
self.assertEqual(
|
|
str(result.exception),
|
|
"Either a token or a login name with a path to a private key need"
|
|
" to be specified"
|
|
)
|
|
|
|
self.mocked_get.assert_not_called()
|
|
self.mocked_put.assert_not_called()
|
|
|
|
def test_login_without_private_key_path(self):
|
|
result = self.runner.invoke(run, ["foobar.com"], env={"LOGIN": "foo"})
|
|
|
|
self.assertEqual(result.exit_code, 1)
|
|
self.assertEqual(
|
|
str(result.exception),
|
|
"Both a login name and the path to a private key need to be specified"
|
|
)
|
|
|
|
self.mocked_get.assert_not_called()
|
|
self.mocked_put.assert_not_called()
|
|
|
|
def test_login_with_private_key_path(self):
|
|
self.mocked_dns.return_value = b"111.420\n"
|
|
self.mocked_get.return_value.json.return_value = {
|
|
"dnsEntries": [
|
|
{
|
|
"name": "@",
|
|
"expire": 60,
|
|
"type": "A",
|
|
"content": "111.421",
|
|
}
|
|
],
|
|
"_links": [
|
|
{
|
|
"rel": "self",
|
|
"link": "https://api.transip.nl/v6/domains/foobar.com/dns",
|
|
},
|
|
{
|
|
"rel": "domain",
|
|
"link": "https://api.transip.nl/v6/domains/foobar.com",
|
|
},
|
|
],
|
|
}
|
|
|
|
self.mocked_session.return_value.json.return_value = {"token": "FOOBAR"}
|
|
|
|
private_key_path = (
|
|
Path(os.path.dirname(__file__)) / "files" / "test-private-key.pem"
|
|
)
|
|
|
|
with self.assertLogs("transip_client.main", level="INFO") as logger:
|
|
result = self.runner.invoke(
|
|
run,
|
|
["foobar.com"],
|
|
env={"LOGIN": "foo", "PRIVATE_KEY_PATH": str(private_key_path)}
|
|
)
|
|
|
|
self.assertEqual(
|
|
logger.output, ["INFO:transip_client.main:Updated domain foobar.com"]
|
|
)
|
|
|
|
self.assertEqual(result.exit_code, 0)
|
|
|
|
self.mocked_get.assert_called_with(
|
|
f"{DEFAULT_API_URL}/domains/foobar.com/dns",
|
|
headers={"Authorization": "Bearer FOOBAR"},
|
|
)
|
|
|
|
expected_json = json.dumps(
|
|
{
|
|
"dnsEntries": [
|
|
{
|
|
"name": "@",
|
|
"expire": 60,
|
|
"type": "A",
|
|
"content": "111.420",
|
|
}
|
|
]
|
|
}
|
|
)
|
|
|
|
self.mocked_put.assert_called_with(
|
|
f"{DEFAULT_API_URL}/domains/foobar.com/dns",
|
|
data=expected_json,
|
|
headers={"Authorization": "Bearer FOOBAR"},
|
|
)
|