test_syslog_ng.py 9.5 KB

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