client_test.py 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904
  1. # -*- coding: utf-8 -*-
  2. """Client unit tests."""
  3. import json
  4. import socket
  5. import sys
  6. import unittest
  7. import random
  8. import warnings
  9. import mock
  10. import requests
  11. import requests.exceptions
  12. import requests_mock
  13. from nose.tools import raises
  14. from mock import patch
  15. from influxdb.influxdb08 import InfluxDBClient
  16. from influxdb.influxdb08.client import session
  17. if sys.version < '3':
  18. import codecs
  19. def u(x):
  20. """Test codec."""
  21. return codecs.unicode_escape_decode(x)[0]
  22. else:
  23. def u(x):
  24. """Test codec."""
  25. return x
  26. def _build_response_object(status_code=200, content=""):
  27. resp = requests.Response()
  28. resp.status_code = status_code
  29. resp._content = content.encode("utf8")
  30. return resp
  31. def _mocked_session(method="GET", status_code=200, content=""):
  32. method = method.upper()
  33. def request(*args, **kwargs):
  34. """Define a request for the _mocked_session."""
  35. c = content
  36. # Check method
  37. assert method == kwargs.get('method', 'GET')
  38. if method == 'POST':
  39. data = kwargs.get('data', None)
  40. if data is not None:
  41. # Data must be a string
  42. assert isinstance(data, str)
  43. # Data must be a JSON string
  44. assert c == json.loads(data, strict=True)
  45. c = data
  46. # Anyway, Content must be a JSON string (or empty string)
  47. if not isinstance(c, str):
  48. c = json.dumps(c)
  49. return _build_response_object(status_code=status_code, content=c)
  50. mocked = patch.object(
  51. session,
  52. 'request',
  53. side_effect=request
  54. )
  55. return mocked
  56. class TestInfluxDBClient(unittest.TestCase):
  57. """Define a TestInfluxDBClient object."""
  58. def setUp(self):
  59. """Set up a TestInfluxDBClient object."""
  60. # By default, raise exceptions on warnings
  61. warnings.simplefilter('error', FutureWarning)
  62. self.dummy_points = [
  63. {
  64. "points": [
  65. ["1", 1, 1.0],
  66. ["2", 2, 2.0]
  67. ],
  68. "name": "foo",
  69. "columns": ["column_one", "column_two", "column_three"]
  70. }
  71. ]
  72. self.dsn_string = 'influxdb://uSr:pWd@host:1886/db'
  73. def test_scheme(self):
  74. """Test database scheme for TestInfluxDBClient object."""
  75. cli = InfluxDBClient('host', 8086, 'username', 'password', 'database')
  76. self.assertEqual(cli._baseurl, 'http://host:8086')
  77. cli = InfluxDBClient(
  78. 'host', 8086, 'username', 'password', 'database', ssl=True
  79. )
  80. self.assertEqual(cli._baseurl, 'https://host:8086')
  81. def test_dsn(self):
  82. """Test datasource name for TestInfluxDBClient object."""
  83. cli = InfluxDBClient.from_dsn(self.dsn_string)
  84. self.assertEqual('http://host:1886', cli._baseurl)
  85. self.assertEqual('uSr', cli._username)
  86. self.assertEqual('pWd', cli._password)
  87. self.assertEqual('db', cli._database)
  88. self.assertFalse(cli._use_udp)
  89. cli = InfluxDBClient.from_dsn('udp+' + self.dsn_string)
  90. self.assertTrue(cli._use_udp)
  91. cli = InfluxDBClient.from_dsn('https+' + self.dsn_string)
  92. self.assertEqual('https://host:1886', cli._baseurl)
  93. cli = InfluxDBClient.from_dsn('https+' + self.dsn_string,
  94. **{'ssl': False})
  95. self.assertEqual('http://host:1886', cli._baseurl)
  96. def test_switch_database(self):
  97. """Test switch database for TestInfluxDBClient object."""
  98. cli = InfluxDBClient('host', 8086, 'username', 'password', 'database')
  99. cli.switch_database('another_database')
  100. self.assertEqual(cli._database, 'another_database')
  101. @raises(FutureWarning)
  102. def test_switch_db_deprecated(self):
  103. """Test deprecated switch database for TestInfluxDBClient object."""
  104. cli = InfluxDBClient('host', 8086, 'username', 'password', 'database')
  105. cli.switch_db('another_database')
  106. self.assertEqual(cli._database, 'another_database')
  107. def test_switch_user(self):
  108. """Test switch user for TestInfluxDBClient object."""
  109. cli = InfluxDBClient('host', 8086, 'username', 'password', 'database')
  110. cli.switch_user('another_username', 'another_password')
  111. self.assertEqual(cli._username, 'another_username')
  112. self.assertEqual(cli._password, 'another_password')
  113. def test_write(self):
  114. """Test write to database for TestInfluxDBClient object."""
  115. with requests_mock.Mocker() as m:
  116. m.register_uri(
  117. requests_mock.POST,
  118. "http://localhost:8086/write"
  119. )
  120. cli = InfluxDBClient(database='db')
  121. cli.write(
  122. {"database": "mydb",
  123. "retentionPolicy": "mypolicy",
  124. "points": [{"name": "cpu_load_short",
  125. "tags": {"host": "server01",
  126. "region": "us-west"},
  127. "timestamp": "2009-11-10T23:00:00Z",
  128. "values": {"value": 0.64}}]}
  129. )
  130. self.assertEqual(
  131. json.loads(m.last_request.body),
  132. {"database": "mydb",
  133. "retentionPolicy": "mypolicy",
  134. "points": [{"name": "cpu_load_short",
  135. "tags": {"host": "server01",
  136. "region": "us-west"},
  137. "timestamp": "2009-11-10T23:00:00Z",
  138. "values": {"value": 0.64}}]}
  139. )
  140. def test_write_points(self):
  141. """Test write points for TestInfluxDBClient object."""
  142. with requests_mock.Mocker() as m:
  143. m.register_uri(
  144. requests_mock.POST,
  145. "http://localhost:8086/db/db/series"
  146. )
  147. cli = InfluxDBClient(database='db')
  148. cli.write_points(
  149. self.dummy_points
  150. )
  151. self.assertListEqual(
  152. json.loads(m.last_request.body),
  153. self.dummy_points
  154. )
  155. def test_write_points_string(self):
  156. """Test write string points for TestInfluxDBClient object."""
  157. with requests_mock.Mocker() as m:
  158. m.register_uri(
  159. requests_mock.POST,
  160. "http://localhost:8086/db/db/series"
  161. )
  162. cli = InfluxDBClient(database='db')
  163. cli.write_points(
  164. str(json.dumps(self.dummy_points))
  165. )
  166. self.assertListEqual(
  167. json.loads(m.last_request.body),
  168. self.dummy_points
  169. )
  170. def test_write_points_batch(self):
  171. """Test write batch points for TestInfluxDBClient object."""
  172. with requests_mock.Mocker() as m:
  173. m.register_uri(requests_mock.POST,
  174. "http://localhost:8086/db/db/series")
  175. cli = InfluxDBClient('localhost', 8086,
  176. 'username', 'password', 'db')
  177. cli.write_points(data=self.dummy_points, batch_size=2)
  178. self.assertEqual(1, m.call_count)
  179. def test_write_points_batch_invalid_size(self):
  180. """Test write batch points invalid size for TestInfluxDBClient."""
  181. with requests_mock.Mocker() as m:
  182. m.register_uri(requests_mock.POST,
  183. "http://localhost:8086/db/db/series")
  184. cli = InfluxDBClient('localhost', 8086,
  185. 'username', 'password', 'db')
  186. cli.write_points(data=self.dummy_points, batch_size=-2)
  187. self.assertEqual(1, m.call_count)
  188. def test_write_points_batch_multiple_series(self):
  189. """Test write points batch multiple series."""
  190. dummy_points = [
  191. {"points": [["1", 1, 1.0], ["2", 2, 2.0], ["3", 3, 3.0],
  192. ["4", 4, 4.0], ["5", 5, 5.0]],
  193. "name": "foo",
  194. "columns": ["val1", "val2", "val3"]},
  195. {"points": [["1", 1, 1.0], ["2", 2, 2.0], ["3", 3, 3.0],
  196. ["4", 4, 4.0], ["5", 5, 5.0], ["6", 6, 6.0],
  197. ["7", 7, 7.0], ["8", 8, 8.0]],
  198. "name": "bar",
  199. "columns": ["val1", "val2", "val3"]},
  200. ]
  201. expected_last_body = [{'points': [['7', 7, 7.0], ['8', 8, 8.0]],
  202. 'name': 'bar',
  203. 'columns': ['val1', 'val2', 'val3']}]
  204. with requests_mock.Mocker() as m:
  205. m.register_uri(requests_mock.POST,
  206. "http://localhost:8086/db/db/series")
  207. cli = InfluxDBClient('localhost', 8086,
  208. 'username', 'password', 'db')
  209. cli.write_points(data=dummy_points, batch_size=3)
  210. self.assertEqual(m.call_count, 5)
  211. self.assertEqual(expected_last_body, m.request_history[4].json())
  212. def test_write_points_udp(self):
  213. """Test write points UDP for TestInfluxDBClient object."""
  214. s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
  215. port = random.randint(4000, 8000)
  216. s.bind(('0.0.0.0', port))
  217. cli = InfluxDBClient(
  218. 'localhost', 8086, 'root', 'root',
  219. 'test', use_udp=True, udp_port=port
  220. )
  221. cli.write_points(self.dummy_points)
  222. received_data, addr = s.recvfrom(1024)
  223. self.assertEqual(self.dummy_points,
  224. json.loads(received_data.decode(), strict=True))
  225. def test_write_bad_precision_udp(self):
  226. """Test write UDP w/bad precision."""
  227. cli = InfluxDBClient(
  228. 'localhost', 8086, 'root', 'root',
  229. 'test', use_udp=True, udp_port=4444
  230. )
  231. with self.assertRaisesRegexp(
  232. Exception,
  233. "InfluxDB only supports seconds precision for udp writes"
  234. ):
  235. cli.write_points(
  236. self.dummy_points,
  237. time_precision='ms'
  238. )
  239. @raises(Exception)
  240. def test_write_points_fails(self):
  241. """Test failed write points for TestInfluxDBClient object."""
  242. with _mocked_session('post', 500):
  243. cli = InfluxDBClient('host', 8086, 'username', 'password', 'db')
  244. cli.write_points([])
  245. def test_write_points_with_precision(self):
  246. """Test write points with precision."""
  247. with _mocked_session('post', 200, self.dummy_points):
  248. cli = InfluxDBClient('host', 8086, 'username', 'password', 'db')
  249. self.assertTrue(cli.write_points(self.dummy_points))
  250. def test_write_points_bad_precision(self):
  251. """Test write points with bad precision."""
  252. cli = InfluxDBClient()
  253. with self.assertRaisesRegexp(
  254. Exception,
  255. "Invalid time precision is given. \(use 's', 'm', 'ms' or 'u'\)"
  256. ):
  257. cli.write_points(
  258. self.dummy_points,
  259. time_precision='g'
  260. )
  261. @raises(Exception)
  262. def test_write_points_with_precision_fails(self):
  263. """Test write points where precision fails."""
  264. with _mocked_session('post', 500):
  265. cli = InfluxDBClient('host', 8086, 'username', 'password', 'db')
  266. cli.write_points_with_precision([])
  267. def test_delete_points(self):
  268. """Test delete points for TestInfluxDBClient object."""
  269. with _mocked_session('delete', 204) as mocked:
  270. cli = InfluxDBClient('host', 8086, 'username', 'password', 'db')
  271. self.assertTrue(cli.delete_points("foo"))
  272. self.assertEqual(len(mocked.call_args_list), 1)
  273. args, kwds = mocked.call_args_list[0]
  274. self.assertEqual(kwds['params'],
  275. {'u': 'username', 'p': 'password'})
  276. self.assertEqual(kwds['url'], 'http://host:8086/db/db/series/foo')
  277. @raises(Exception)
  278. def test_delete_points_with_wrong_name(self):
  279. """Test delete points with wrong name."""
  280. with _mocked_session('delete', 400):
  281. cli = InfluxDBClient('host', 8086, 'username', 'password', 'db')
  282. cli.delete_points("nonexist")
  283. @raises(NotImplementedError)
  284. def test_create_scheduled_delete(self):
  285. """Test create scheduled deletes."""
  286. cli = InfluxDBClient('host', 8086, 'username', 'password', 'db')
  287. cli.create_scheduled_delete([])
  288. @raises(NotImplementedError)
  289. def test_get_list_scheduled_delete(self):
  290. """Test get schedule list of deletes TestInfluxDBClient."""
  291. cli = InfluxDBClient('host', 8086, 'username', 'password', 'db')
  292. cli.get_list_scheduled_delete()
  293. @raises(NotImplementedError)
  294. def test_remove_scheduled_delete(self):
  295. """Test remove scheduled delete TestInfluxDBClient."""
  296. cli = InfluxDBClient('host', 8086, 'username', 'password', 'db')
  297. cli.remove_scheduled_delete(1)
  298. def test_query(self):
  299. """Test query for TestInfluxDBClient object."""
  300. data = [
  301. {
  302. "name": "foo",
  303. "columns": ["time", "sequence_number", "column_one"],
  304. "points": [
  305. [1383876043, 16, "2"], [1383876043, 15, "1"],
  306. [1383876035, 14, "2"], [1383876035, 13, "1"]
  307. ]
  308. }
  309. ]
  310. with _mocked_session('get', 200, data):
  311. cli = InfluxDBClient('host', 8086, 'username', 'password', 'db')
  312. result = cli.query('select column_one from foo;')
  313. self.assertEqual(len(result[0]['points']), 4)
  314. def test_query_chunked(self):
  315. """Test chunked query for TestInfluxDBClient object."""
  316. cli = InfluxDBClient(database='db')
  317. example_object = {
  318. 'points': [
  319. [1415206250119, 40001, 667],
  320. [1415206244555, 30001, 7],
  321. [1415206228241, 20001, 788],
  322. [1415206212980, 10001, 555],
  323. [1415197271586, 10001, 23]
  324. ],
  325. 'name': 'foo',
  326. 'columns': [
  327. 'time',
  328. 'sequence_number',
  329. 'val'
  330. ]
  331. }
  332. example_response = \
  333. json.dumps(example_object) + json.dumps(example_object)
  334. with requests_mock.Mocker() as m:
  335. m.register_uri(
  336. requests_mock.GET,
  337. "http://localhost:8086/db/db/series",
  338. text=example_response
  339. )
  340. self.assertListEqual(
  341. cli.query('select * from foo', chunked=True),
  342. [example_object, example_object]
  343. )
  344. def test_query_chunked_unicode(self):
  345. """Test unicode chunked query for TestInfluxDBClient object."""
  346. cli = InfluxDBClient(database='db')
  347. example_object = {
  348. 'points': [
  349. [1415206212980, 10001, u('unicode-\xcf\x89')],
  350. [1415197271586, 10001, u('more-unicode-\xcf\x90')]
  351. ],
  352. 'name': 'foo',
  353. 'columns': [
  354. 'time',
  355. 'sequence_number',
  356. 'val'
  357. ]
  358. }
  359. example_response = \
  360. json.dumps(example_object) + json.dumps(example_object)
  361. with requests_mock.Mocker() as m:
  362. m.register_uri(
  363. requests_mock.GET,
  364. "http://localhost:8086/db/db/series",
  365. text=example_response
  366. )
  367. self.assertListEqual(
  368. cli.query('select * from foo', chunked=True),
  369. [example_object, example_object]
  370. )
  371. @raises(Exception)
  372. def test_query_fail(self):
  373. """Test failed query for TestInfluxDBClient."""
  374. with _mocked_session('get', 401):
  375. cli = InfluxDBClient('host', 8086, 'username', 'password', 'db')
  376. cli.query('select column_one from foo;')
  377. def test_query_bad_precision(self):
  378. """Test query with bad precision for TestInfluxDBClient."""
  379. cli = InfluxDBClient()
  380. with self.assertRaisesRegexp(
  381. Exception,
  382. "Invalid time precision is given. \(use 's', 'm', 'ms' or 'u'\)"
  383. ):
  384. cli.query('select column_one from foo', time_precision='g')
  385. def test_create_database(self):
  386. """Test create database for TestInfluxDBClient."""
  387. with _mocked_session('post', 201, {"name": "new_db"}):
  388. cli = InfluxDBClient('host', 8086, 'username', 'password', 'db')
  389. self.assertTrue(cli.create_database('new_db'))
  390. @raises(Exception)
  391. def test_create_database_fails(self):
  392. """Test failed create database for TestInfluxDBClient."""
  393. with _mocked_session('post', 401):
  394. cli = InfluxDBClient('host', 8086, 'username', 'password', 'db')
  395. cli.create_database('new_db')
  396. def test_delete_database(self):
  397. """Test delete database for TestInfluxDBClient."""
  398. with _mocked_session('delete', 204):
  399. cli = InfluxDBClient('host', 8086, 'username', 'password', 'db')
  400. self.assertTrue(cli.delete_database('old_db'))
  401. @raises(Exception)
  402. def test_delete_database_fails(self):
  403. """Test failed delete database for TestInfluxDBClient."""
  404. with _mocked_session('delete', 401):
  405. cli = InfluxDBClient('host', 8086, 'username', 'password', 'db')
  406. cli.delete_database('old_db')
  407. def test_get_list_database(self):
  408. """Test get list of databases for TestInfluxDBClient."""
  409. data = [
  410. {"name": "a_db"}
  411. ]
  412. with _mocked_session('get', 200, data):
  413. cli = InfluxDBClient('host', 8086, 'username', 'password')
  414. self.assertEqual(len(cli.get_list_database()), 1)
  415. self.assertEqual(cli.get_list_database()[0]['name'], 'a_db')
  416. @raises(Exception)
  417. def test_get_list_database_fails(self):
  418. """Test failed get list of databases for TestInfluxDBClient."""
  419. with _mocked_session('get', 401):
  420. cli = InfluxDBClient('host', 8086, 'username', 'password')
  421. cli.get_list_database()
  422. @raises(FutureWarning)
  423. def test_get_database_list_deprecated(self):
  424. """Test deprecated get database list for TestInfluxDBClient."""
  425. data = [
  426. {"name": "a_db"}
  427. ]
  428. with _mocked_session('get', 200, data):
  429. cli = InfluxDBClient('host', 8086, 'username', 'password')
  430. self.assertEqual(len(cli.get_database_list()), 1)
  431. self.assertEqual(cli.get_database_list()[0]['name'], 'a_db')
  432. def test_delete_series(self):
  433. """Test delete series for TestInfluxDBClient."""
  434. with _mocked_session('delete', 204):
  435. cli = InfluxDBClient('host', 8086, 'username', 'password', 'db')
  436. cli.delete_series('old_series')
  437. @raises(Exception)
  438. def test_delete_series_fails(self):
  439. """Test failed delete series for TestInfluxDBClient."""
  440. with _mocked_session('delete', 401):
  441. cli = InfluxDBClient('host', 8086, 'username', 'password', 'db')
  442. cli.delete_series('old_series')
  443. def test_get_series_list(self):
  444. """Test get list of series for TestInfluxDBClient."""
  445. cli = InfluxDBClient(database='db')
  446. with requests_mock.Mocker() as m:
  447. example_response = \
  448. '[{"name":"list_series_result","columns":' \
  449. '["time","name"],"points":[[0,"foo"],[0,"bar"]]}]'
  450. m.register_uri(
  451. requests_mock.GET,
  452. "http://localhost:8086/db/db/series",
  453. text=example_response
  454. )
  455. self.assertListEqual(
  456. cli.get_list_series(),
  457. ['foo', 'bar']
  458. )
  459. def test_get_continuous_queries(self):
  460. """Test get continuous queries for TestInfluxDBClient."""
  461. cli = InfluxDBClient(database='db')
  462. with requests_mock.Mocker() as m:
  463. # Tip: put this in a json linter!
  464. example_response = '[ { "name": "continuous queries", "columns"' \
  465. ': [ "time", "id", "query" ], "points": [ [ ' \
  466. '0, 1, "select foo(bar,95) from \\"foo_bar' \
  467. 's\\" group by time(5m) into response_times.' \
  468. 'percentiles.5m.95" ], [ 0, 2, "select perce' \
  469. 'ntile(value,95) from \\"response_times\\" g' \
  470. 'roup by time(5m) into response_times.percen' \
  471. 'tiles.5m.95" ] ] } ]'
  472. m.register_uri(
  473. requests_mock.GET,
  474. "http://localhost:8086/db/db/series",
  475. text=example_response
  476. )
  477. self.assertListEqual(
  478. cli.get_list_continuous_queries(),
  479. [
  480. 'select foo(bar,95) from "foo_bars" group '
  481. 'by time(5m) into response_times.percentiles.5m.95',
  482. 'select percentile(value,95) from "response_times" group '
  483. 'by time(5m) into response_times.percentiles.5m.95'
  484. ]
  485. )
  486. def test_get_list_cluster_admins(self):
  487. """Test get list of cluster admins, not implemented."""
  488. pass
  489. def test_add_cluster_admin(self):
  490. """Test add cluster admin for TestInfluxDBClient."""
  491. with requests_mock.Mocker() as m:
  492. m.register_uri(
  493. requests_mock.POST,
  494. "http://localhost:8086/cluster_admins"
  495. )
  496. cli = InfluxDBClient(database='db')
  497. cli.add_cluster_admin(
  498. new_username='paul',
  499. new_password='laup'
  500. )
  501. self.assertDictEqual(
  502. json.loads(m.last_request.body),
  503. {
  504. 'name': 'paul',
  505. 'password': 'laup'
  506. }
  507. )
  508. def test_update_cluster_admin_password(self):
  509. """Test update cluster admin pass for TestInfluxDBClient."""
  510. with requests_mock.Mocker() as m:
  511. m.register_uri(
  512. requests_mock.POST,
  513. "http://localhost:8086/cluster_admins/paul"
  514. )
  515. cli = InfluxDBClient(database='db')
  516. cli.update_cluster_admin_password(
  517. username='paul',
  518. new_password='laup'
  519. )
  520. self.assertDictEqual(
  521. json.loads(m.last_request.body),
  522. {'password': 'laup'}
  523. )
  524. def test_delete_cluster_admin(self):
  525. """Test delete cluster admin for TestInfluxDBClient."""
  526. with requests_mock.Mocker() as m:
  527. m.register_uri(
  528. requests_mock.DELETE,
  529. "http://localhost:8086/cluster_admins/paul",
  530. status_code=200,
  531. )
  532. cli = InfluxDBClient(database='db')
  533. cli.delete_cluster_admin(username='paul')
  534. self.assertIsNone(m.last_request.body)
  535. def test_set_database_admin(self):
  536. """Test set database admin for TestInfluxDBClient."""
  537. pass
  538. def test_unset_database_admin(self):
  539. """Test unset database admin for TestInfluxDBClient."""
  540. pass
  541. def test_alter_database_admin(self):
  542. """Test alter database admin for TestInfluxDBClient."""
  543. with requests_mock.Mocker() as m:
  544. m.register_uri(
  545. requests_mock.POST,
  546. "http://localhost:8086/db/db/users/paul"
  547. )
  548. cli = InfluxDBClient(database='db')
  549. cli.alter_database_admin(
  550. username='paul',
  551. is_admin=False
  552. )
  553. self.assertDictEqual(
  554. json.loads(m.last_request.body),
  555. {
  556. 'admin': False
  557. }
  558. )
  559. @raises(NotImplementedError)
  560. def test_get_list_database_admins(self):
  561. """Test get list of database admins for TestInfluxDBClient."""
  562. cli = InfluxDBClient('host', 8086, 'username', 'password', 'db')
  563. cli.get_list_database_admins()
  564. @raises(NotImplementedError)
  565. def test_add_database_admin(self):
  566. """Test add database admins for TestInfluxDBClient."""
  567. cli = InfluxDBClient('host', 8086, 'username', 'password', 'db')
  568. cli.add_database_admin('admin', 'admin_secret_password')
  569. @raises(NotImplementedError)
  570. def test_update_database_admin_password(self):
  571. """Test update database admin pass for TestInfluxDBClient."""
  572. cli = InfluxDBClient('host', 8086, 'username', 'password', 'db')
  573. cli.update_database_admin_password('admin', 'admin_secret_password')
  574. @raises(NotImplementedError)
  575. def test_delete_database_admin(self):
  576. """Test delete database admin for TestInfluxDBClient."""
  577. cli = InfluxDBClient('host', 8086, 'username', 'password', 'db')
  578. cli.delete_database_admin('admin')
  579. def test_get_database_users(self):
  580. """Test get database users for TestInfluxDBClient."""
  581. cli = InfluxDBClient('localhost', 8086, 'username', 'password', 'db')
  582. example_response = \
  583. '[{"name":"paul","isAdmin":false,"writeTo":".*","readFrom":".*"},'\
  584. '{"name":"bobby","isAdmin":false,"writeTo":".*","readFrom":".*"}]'
  585. with requests_mock.Mocker() as m:
  586. m.register_uri(
  587. requests_mock.GET,
  588. "http://localhost:8086/db/db/users",
  589. text=example_response
  590. )
  591. users = cli.get_database_users()
  592. self.assertEqual(json.loads(example_response), users)
  593. def test_add_database_user(self):
  594. """Test add database user for TestInfluxDBClient."""
  595. with requests_mock.Mocker() as m:
  596. m.register_uri(
  597. requests_mock.POST,
  598. "http://localhost:8086/db/db/users"
  599. )
  600. cli = InfluxDBClient(database='db')
  601. cli.add_database_user(
  602. new_username='paul',
  603. new_password='laup',
  604. permissions=('.*', '.*')
  605. )
  606. self.assertDictEqual(
  607. json.loads(m.last_request.body),
  608. {
  609. 'writeTo': '.*',
  610. 'password': 'laup',
  611. 'readFrom': '.*',
  612. 'name': 'paul'
  613. }
  614. )
  615. def test_add_database_user_bad_permissions(self):
  616. """Test add database user with bad perms for TestInfluxDBClient."""
  617. cli = InfluxDBClient()
  618. with self.assertRaisesRegexp(
  619. Exception,
  620. "'permissions' must be \(readFrom, writeTo\) tuple"
  621. ):
  622. cli.add_database_user(
  623. new_password='paul',
  624. new_username='paul',
  625. permissions=('hello', 'hello', 'hello')
  626. )
  627. def test_alter_database_user_password(self):
  628. """Test alter database user pass for TestInfluxDBClient."""
  629. with requests_mock.Mocker() as m:
  630. m.register_uri(
  631. requests_mock.POST,
  632. "http://localhost:8086/db/db/users/paul"
  633. )
  634. cli = InfluxDBClient(database='db')
  635. cli.alter_database_user(
  636. username='paul',
  637. password='n3wp4ss!'
  638. )
  639. self.assertDictEqual(
  640. json.loads(m.last_request.body),
  641. {
  642. 'password': 'n3wp4ss!'
  643. }
  644. )
  645. def test_alter_database_user_permissions(self):
  646. """Test alter database user perms for TestInfluxDBClient."""
  647. with requests_mock.Mocker() as m:
  648. m.register_uri(
  649. requests_mock.POST,
  650. "http://localhost:8086/db/db/users/paul"
  651. )
  652. cli = InfluxDBClient(database='db')
  653. cli.alter_database_user(
  654. username='paul',
  655. permissions=('^$', '.*')
  656. )
  657. self.assertDictEqual(
  658. json.loads(m.last_request.body),
  659. {
  660. 'readFrom': '^$',
  661. 'writeTo': '.*'
  662. }
  663. )
  664. def test_alter_database_user_password_and_permissions(self):
  665. """Test alter database user pass and perms for TestInfluxDBClient."""
  666. with requests_mock.Mocker() as m:
  667. m.register_uri(
  668. requests_mock.POST,
  669. "http://localhost:8086/db/db/users/paul"
  670. )
  671. cli = InfluxDBClient(database='db')
  672. cli.alter_database_user(
  673. username='paul',
  674. password='n3wp4ss!',
  675. permissions=('^$', '.*')
  676. )
  677. self.assertDictEqual(
  678. json.loads(m.last_request.body),
  679. {
  680. 'password': 'n3wp4ss!',
  681. 'readFrom': '^$',
  682. 'writeTo': '.*'
  683. }
  684. )
  685. def test_update_database_user_password_current_user(self):
  686. """Test update database user pass for TestInfluxDBClient."""
  687. cli = InfluxDBClient(
  688. username='root',
  689. password='hello',
  690. database='database'
  691. )
  692. with requests_mock.Mocker() as m:
  693. m.register_uri(
  694. requests_mock.POST,
  695. "http://localhost:8086/db/database/users/root"
  696. )
  697. cli.update_database_user_password(
  698. username='root',
  699. new_password='bye'
  700. )
  701. self.assertEqual(cli._password, 'bye')
  702. def test_delete_database_user(self):
  703. """Test delete database user for TestInfluxDBClient."""
  704. with requests_mock.Mocker() as m:
  705. m.register_uri(
  706. requests_mock.DELETE,
  707. "http://localhost:8086/db/db/users/paul"
  708. )
  709. cli = InfluxDBClient(database='db')
  710. cli.delete_database_user(username='paul')
  711. self.assertIsNone(m.last_request.body)
  712. @raises(NotImplementedError)
  713. def test_update_permission(self):
  714. """Test update permission for TestInfluxDBClient."""
  715. cli = InfluxDBClient('host', 8086, 'username', 'password', 'db')
  716. cli.update_permission('admin', [])
  717. @mock.patch('requests.Session.request')
  718. def test_request_retry(self, mock_request):
  719. """Test that two connection errors will be handled."""
  720. class CustomMock(object):
  721. """Define CustomMock object."""
  722. def __init__(self):
  723. self.i = 0
  724. def connection_error(self, *args, **kwargs):
  725. """Test connection error in CustomMock."""
  726. self.i += 1
  727. if self.i < 3:
  728. raise requests.exceptions.ConnectionError
  729. else:
  730. r = requests.Response()
  731. r.status_code = 200
  732. return r
  733. mock_request.side_effect = CustomMock().connection_error
  734. cli = InfluxDBClient(database='db')
  735. cli.write_points(
  736. self.dummy_points
  737. )
  738. @mock.patch('requests.Session.request')
  739. def test_request_retry_raises(self, mock_request):
  740. """Test that three connection errors will not be handled."""
  741. class CustomMock(object):
  742. """Define CustomMock object."""
  743. def __init__(self):
  744. """Initialize the object."""
  745. self.i = 0
  746. def connection_error(self, *args, **kwargs):
  747. """Test the connection error for CustomMock."""
  748. self.i += 1
  749. if self.i < 4:
  750. raise requests.exceptions.ConnectionError
  751. else:
  752. r = requests.Response()
  753. r.status_code = 200
  754. return r
  755. mock_request.side_effect = CustomMock().connection_error
  756. cli = InfluxDBClient(database='db')
  757. with self.assertRaises(requests.exceptions.ConnectionError):
  758. cli.write_points(self.dummy_points)