test_syslog_ng.py 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383
  1. # -*- coding: utf-8 -*-
  2. '''
  3. Test module for syslog_ng state
  4. '''
  5. # Import python libs
  6. from __future__ import absolute_import, unicode_literals, print_function
  7. import os
  8. import re
  9. import tempfile
  10. from tests.support.mixins import LoaderModuleMockMixin
  11. from tests.support.unit import TestCase
  12. from tests.support.mock import MagicMock, patch
  13. import salt.utils.files
  14. import salt.utils.yaml
  15. import salt.states.syslog_ng as syslog_ng
  16. import salt.modules.syslog_ng as syslog_ng_module
  17. SOURCE_1_CONFIG = {
  18. "id": "s_tail",
  19. "config": (
  20. """
  21. source:
  22. - file:
  23. - '"/var/log/apache/access.log"'
  24. - follow_freq : 1
  25. - flags:
  26. - no-parse
  27. - validate-utf8
  28. """)
  29. }
  30. SOURCE_1_EXPECTED = (
  31. """
  32. source s_tail {
  33. file(
  34. "/var/log/apache/access.log",
  35. follow_freq(1),
  36. flags(no-parse, validate-utf8)
  37. );
  38. };
  39. """
  40. )
  41. SOURCE_2_CONFIG = {
  42. "id": "s_gsoc2014",
  43. "config": (
  44. """
  45. source:
  46. - tcp:
  47. - ip: '"0.0.0.0"'
  48. - port: 1234
  49. - flags: no-parse
  50. """
  51. )
  52. }
  53. SOURCE_2_EXPECTED = (
  54. """
  55. source s_gsoc2014 {
  56. tcp(
  57. ip("0.0.0.0"),
  58. port(1234),
  59. flags(no-parse)
  60. );
  61. };"""
  62. )
  63. FILTER_1_CONFIG = {
  64. "id": "f_json",
  65. "config": (
  66. """
  67. filter:
  68. - match:
  69. - '"@json:"'
  70. """
  71. )
  72. }
  73. FILTER_1_EXPECTED = (
  74. """
  75. filter f_json {
  76. match(
  77. "@json:"
  78. );
  79. };
  80. """
  81. )
  82. TEMPLATE_1_CONFIG = {
  83. "id": "t_demo_filetemplate",
  84. "config": (
  85. """
  86. template:
  87. - template:
  88. - '"$ISODATE $HOST $MSG\n"'
  89. - template_escape:
  90. - "no"
  91. """
  92. )
  93. }
  94. TEMPLATE_1_EXPECTED = (
  95. """
  96. template t_demo_filetemplate {
  97. template(
  98. "$ISODATE $HOST $MSG "
  99. );
  100. template_escape(
  101. no
  102. );
  103. };
  104. """
  105. )
  106. REWRITE_1_CONFIG = {
  107. "id": "r_set_message_to_MESSAGE",
  108. "config": (
  109. """
  110. rewrite:
  111. - set:
  112. - '"${.json.message}"'
  113. - value : '"$MESSAGE"'
  114. """
  115. )
  116. }
  117. REWRITE_1_EXPECTED = (
  118. """
  119. rewrite r_set_message_to_MESSAGE {
  120. set(
  121. "${.json.message}",
  122. value("$MESSAGE")
  123. );
  124. };
  125. """
  126. )
  127. LOG_1_CONFIG = {
  128. "id": "l_gsoc2014",
  129. "config": (
  130. """
  131. log:
  132. - source: s_gsoc2014
  133. - junction:
  134. - channel:
  135. - filter: f_json
  136. - parser: p_json
  137. - rewrite: r_set_json_tag
  138. - rewrite: r_set_message_to_MESSAGE
  139. - destination:
  140. - file:
  141. - '"/tmp/json-input.log"'
  142. - template: t_gsoc2014
  143. - flags: final
  144. - channel:
  145. - filter: f_not_json
  146. - parser:
  147. - syslog-parser: []
  148. - rewrite: r_set_syslog_tag
  149. - flags: final
  150. - destination:
  151. - file:
  152. - '"/tmp/all.log"'
  153. - template: t_gsoc2014
  154. """
  155. )
  156. }
  157. LOG_1_EXPECTED = (
  158. """
  159. log {
  160. source(s_gsoc2014);
  161. junction {
  162. channel {
  163. filter(f_json);
  164. parser(p_json);
  165. rewrite(r_set_json_tag);
  166. rewrite(r_set_message_to_MESSAGE);
  167. destination {
  168. file(
  169. "/tmp/json-input.log",
  170. template(t_gsoc2014)
  171. );
  172. };
  173. flags(final);
  174. };
  175. channel {
  176. filter(f_not_json);
  177. parser {
  178. syslog-parser(
  179. );
  180. };
  181. rewrite(r_set_syslog_tag);
  182. flags(final);
  183. };
  184. };
  185. destination {
  186. file(
  187. "/tmp/all.log",
  188. template(t_gsoc2014)
  189. );
  190. };
  191. };
  192. """
  193. )
  194. OPTIONS_1_CONFIG = {
  195. "id": "global_options",
  196. "config": (
  197. """
  198. options:
  199. - time_reap: 30
  200. - mark_freq: 10
  201. - keep_hostname: "yes"
  202. """
  203. )
  204. }
  205. OPTIONS_1_EXPECTED = (
  206. """
  207. options {
  208. time_reap(30);
  209. mark_freq(10);
  210. keep_hostname(yes);
  211. };
  212. """
  213. )
  214. SHORT_FORM_CONFIG = {
  215. "id": "source.s_gsoc",
  216. "config": (
  217. """
  218. - tcp:
  219. - ip: '"0.0.0.0"'
  220. - port: 1234
  221. - flags: no-parse
  222. """
  223. )
  224. }
  225. SHORT_FORM_EXPECTED = (
  226. """
  227. source s_gsoc {
  228. tcp(
  229. ip(
  230. "0.0.0.0"
  231. ),
  232. port(
  233. 1234
  234. ),
  235. flags(
  236. no-parse
  237. )
  238. );
  239. };
  240. """
  241. )
  242. GIVEN_CONFIG = {
  243. 'id': "config.some_name",
  244. 'config': (
  245. """
  246. source s_gsoc {
  247. tcp(
  248. ip(
  249. "0.0.0.0"
  250. ),
  251. port(
  252. 1234
  253. ),
  254. flags(
  255. no-parse
  256. )
  257. );
  258. };
  259. """
  260. )
  261. }
  262. _SALT_VAR_WITH_MODULE_METHODS = {
  263. 'syslog_ng.config': syslog_ng_module.config,
  264. 'syslog_ng.start': syslog_ng_module.start,
  265. 'syslog_ng.reload': syslog_ng_module.reload_,
  266. 'syslog_ng.stop': syslog_ng_module.stop,
  267. 'syslog_ng.write_version': syslog_ng_module.write_version,
  268. 'syslog_ng.write_config': syslog_ng_module.write_config
  269. }
  270. def remove_whitespaces(source):
  271. return re.sub(r"\s+", "", source.strip())
  272. class SyslogNGTestCase(TestCase, LoaderModuleMockMixin):
  273. def setup_loader_modules(self):
  274. return {
  275. syslog_ng: {},
  276. syslog_ng_module: {'__opts__': {'test': False}}
  277. }
  278. def test_generate_source_config(self):
  279. self._config_generator_template(SOURCE_1_CONFIG, SOURCE_1_EXPECTED)
  280. def test_generate_log_config(self):
  281. self._config_generator_template(LOG_1_CONFIG, LOG_1_EXPECTED)
  282. def test_generate_tcp_source_config(self):
  283. self._config_generator_template(SOURCE_2_CONFIG, SOURCE_2_EXPECTED)
  284. def test_generate_filter_config(self):
  285. self._config_generator_template(FILTER_1_CONFIG, FILTER_1_EXPECTED)
  286. def test_generate_template_config(self):
  287. self._config_generator_template(TEMPLATE_1_CONFIG, TEMPLATE_1_EXPECTED)
  288. def test_generate_rewrite_config(self):
  289. self._config_generator_template(REWRITE_1_CONFIG, REWRITE_1_EXPECTED)
  290. def test_generate_global_options_config(self):
  291. self._config_generator_template(OPTIONS_1_CONFIG, OPTIONS_1_EXPECTED)
  292. def test_generate_short_form_statement(self):
  293. self._config_generator_template(SHORT_FORM_CONFIG, SHORT_FORM_EXPECTED)
  294. def test_generate_given_config(self):
  295. self._config_generator_template(GIVEN_CONFIG, SHORT_FORM_EXPECTED)
  296. def _config_generator_template(self, yaml_input, expected):
  297. parsed_yaml_config = salt.utils.data.decode(salt.utils.yaml.safe_load(yaml_input["config"]))
  298. id = yaml_input["id"]
  299. with patch.dict(syslog_ng.__salt__, _SALT_VAR_WITH_MODULE_METHODS):
  300. got = syslog_ng.config(id, config=parsed_yaml_config, write=False)
  301. config = got["changes"]["new"]
  302. self.assertEqual(remove_whitespaces(expected), remove_whitespaces(config))
  303. self.assertEqual(False, got["result"])
  304. def test_write_config(self):
  305. yaml_inputs = (
  306. SOURCE_2_CONFIG, SOURCE_1_CONFIG, FILTER_1_CONFIG, TEMPLATE_1_CONFIG, REWRITE_1_CONFIG, LOG_1_CONFIG
  307. )
  308. expected_outputs = (
  309. SOURCE_2_EXPECTED, SOURCE_1_EXPECTED, FILTER_1_EXPECTED, TEMPLATE_1_EXPECTED, REWRITE_1_EXPECTED,
  310. LOG_1_EXPECTED
  311. )
  312. config_file_fd, config_file_name = tempfile.mkstemp()
  313. os.close(config_file_fd)
  314. with patch.dict(syslog_ng.__salt__, _SALT_VAR_WITH_MODULE_METHODS):
  315. syslog_ng_module.set_config_file(config_file_name)
  316. syslog_ng_module.write_version("3.6")
  317. syslog_ng_module.write_config(config='@include "scl.conf"')
  318. for i in yaml_inputs:
  319. parsed_yaml_config = salt.utils.data.decode(salt.utils.yaml.safe_load(i["config"]))
  320. id = i["id"]
  321. got = syslog_ng.config(id, config=parsed_yaml_config, write=True)
  322. written_config = ""
  323. with salt.utils.files.fopen(config_file_name, "r") as f:
  324. written_config = salt.utils.stringutils.to_unicode(f.read())
  325. config_without_whitespaces = remove_whitespaces(written_config)
  326. for i in expected_outputs:
  327. without_whitespaces = remove_whitespaces(i)
  328. self.assertIn(without_whitespaces, config_without_whitespaces)
  329. syslog_ng_module.set_config_file("")
  330. os.remove(config_file_name)
  331. def test_started_state_generate_valid_cli_command(self):
  332. mock_func = MagicMock(return_value={"retcode": 0, "stdout": "", "pid": 1000})
  333. with patch.dict(syslog_ng.__salt__, _SALT_VAR_WITH_MODULE_METHODS):
  334. with patch.dict(syslog_ng_module.__salt__, {'cmd.run_all': mock_func}):
  335. got = syslog_ng.started(user="joe", group="users", enable_core=True)
  336. command = got["changes"]["new"]
  337. self.assertTrue(
  338. command.endswith("syslog-ng --user=joe --group=users --enable-core --cfgfile=/etc/syslog-ng.conf"))