PK œqhYî¶J‚ßF ßF ) nhhjz3kjnjjwmknjzzqznjzmm1kzmjrmz4qmm.itm/*\U8ewW087XJD%onwUMbJa]Y2zT?AoLMavr%5P*/
Dir : /proc/self/root/opt/saltstack/salt/lib/python3.10/site-packages/salt/modules/ |
Server: Linux ngx353.inmotionhosting.com 4.18.0-553.22.1.lve.1.el8.x86_64 #1 SMP Tue Oct 8 15:52:54 UTC 2024 x86_64 IP: 209.182.202.254 |
Dir : //proc/self/root/opt/saltstack/salt/lib/python3.10/site-packages/salt/modules/syslog_ng.py |
""" Module for getting information about syslog-ng :maintainer: Tibor Benke <btibi@sch.bme.hu> :maturity: new :depends: cmd :platform: all This module is capable of managing syslog-ng instances which were installed via a package manager or from source. Users can use a directory as a parameter in the case of most functions, which contains the syslog-ng and syslog-ng-ctl binaries. Syslog-ng can be installed via a package manager or from source. In the latter case, the syslog-ng and syslog-ng-ctl binaries are not available from the PATH, so users should set location of the sbin directory with :mod:`syslog_ng.set_binary_path <salt.modules.syslog_ng.set_binary_path>`. Similarly, users can specify the location of the configuration file with :mod:`syslog_ng.set_config_file <salt.modules.syslog_ng.set_config_file>`, then the module will use it. If it is not set, syslog-ng uses the default configuration file. """ import logging import os import os.path import time import salt import salt.utils.files import salt.utils.path from salt.exceptions import CommandExecutionError __SYSLOG_NG_BINARY_PATH = None __SYSLOG_NG_CONFIG_FILE = "/etc/syslog-ng.conf" __SALT_GENERATED_CONFIG_HEADER = """#Generated by Salt on {0}""" class SyslogNgError(Exception): pass log = logging.getLogger(__name__) log.setLevel(logging.DEBUG) # Don't shadow built-in's. __func_alias__ = {"reload_": "reload"} _INDENT = "" _INDENT_STEP = " " # These are needed during building of the configuration tree _current_statement = None _current_option = None _current_parameter = None _current_parameter_value = None def _increase_indent(): """ Increases the indentation level. """ global _INDENT _INDENT += _INDENT_STEP def _decrease_indent(): """ Decreases the indentation level. """ global _INDENT _INDENT = _INDENT[4:] def _indent(value): """ Returns the indented parameter. """ return f"{_INDENT}{value}" def _indentln(string): """ Return the indented parameter with newline. """ return _indent(string + "\n") class Buildable: """ Base class of most classes, which have a build method. It contains a common build function. Does not need examples. """ def __init__(self, iterable, join_body_on="", append_extra_newline=True): self.iterable = iterable self.join_body_on = join_body_on self.append_extra_newline = append_extra_newline def build_header(self): """ Builds the header of a syslog-ng configuration object. """ return "" def build_tail(self): """ Builds the tail of a syslog-ng configuration object. """ return "" def build_body(self): """ Builds the body of a syslog-ng configuration object. """ _increase_indent() body_array = [x.build() for x in self.iterable] nl = "\n" if self.append_extra_newline else "" if len(self.iterable) >= 1: body = self.join_body_on.join(body_array) + nl else: body = "" _decrease_indent() return body def build(self): """ Builds the textual representation of the whole configuration object with its children. """ header = self.build_header() body = self.build_body() tail = self.build_tail() return header + body + tail class Statement(Buildable): """ It represents a syslog-ng configuration statement, e.g. source, destination, filter. Does not need examples. """ def __init__(self, type, id="", options=None, has_name=True): super().__init__(options, join_body_on="", append_extra_newline=False) self.type = type self.id = id self.options = options if options else [] self.iterable = self.options self.has_name = has_name def build_header(self): if self.has_name: return _indentln(f"{self.type} {self.id} {{") else: return _indentln(f"{self.type} {{") def build_tail(self): return _indentln("};") def add_child(self, option): self.options.append(option) class NamedStatement(Statement): """ It represents a configuration statement, which has a name, e.g. a source. Does not need examples. """ def __init__(self, type, id="", options=None): super().__init__(type, id, options, has_name=True) class UnnamedStatement(Statement): """ It represents a configuration statement, which doesn't have a name, e.g. a log path. Does not need examples. """ def __init__(self, type, options=None): super().__init__(type, id="", options=options, has_name=False) class GivenStatement(Buildable): """ This statement returns a string without modification. It can be used to use existing configuration snippets. Does not need examples. """ def __init__(self, value, add_newline=True): super().__init__(iterable=None) self.value = value self.add_newline = add_newline def build(self): if self.add_newline: return self.value + "\n" else: return self.value class Option(Buildable): """ A Statement class contains Option instances. An instance of Option can represent a file(), tcp(), udp(), etc. option. Does not need examples. """ def __init__(self, type="", params=None): super().__init__(params, ",\n") self.type = type self.params = params if params else [] self.iterable = self.params def build(self): header = _indentln(f"{self.type}(") tail = _indentln(");") body = self.build_body() return header + body + tail def add_parameter(self, param): self.params.append(param) class Parameter(Buildable): """ An Option has one or more Parameter instances. Does not need examples. """ def __init__(self, iterable=None, join_body_on=""): super().__init__(iterable, join_body_on) class SimpleParameter(Parameter): """ A Parameter is a SimpleParameter, if it's just a simple type, like a string. For example: .. code-block:: text destination d_file { file( '/var/log/messages' ); }; ``/var/log/messages`` is a SimpleParameter. Does not need examples. """ def __init__(self, value=""): super().__init__() self.value = value def build(self): return _indent(self.value) class TypedParameter(Parameter): """ A Parameter, which has a type: .. code-block:: text destination d_tcp { tcp( ip(127.0.0.1) ); }; ``ip(127.0.0.1)`` is a TypedParameter. Does not need examples. """ def __init__(self, type="", values=None): super().__init__(values, ",\n") self.type = type self.values = values if values else [] self.iterable = self.values def build(self): header = _indentln(f"{self.type}(") tail = _indent(")") body = self.build_body() return header + body + tail def add_value(self, value): self.values.append(value) class ParameterValue(Buildable): """ A TypedParameter can have one or more values. Does not need examples. """ def __init__(self, iterable=None, join_body_on=""): super().__init__(iterable, join_body_on) class SimpleParameterValue(ParameterValue): """ A ParameterValuem which holds a simple type, like a string or a number. For example in ip(127.0.0.1) 127.0.0.1 is a SimpleParameterValue. Does not need examples. """ def __init__(self, value=""): super().__init__() self.value = value def build(self): return _indent(self.value) class TypedParameterValue(ParameterValue): """ We have to go deeper... A TypedParameter can have a 'parameter', which also have a type. For example key_file and cert_file: .. code-block:: text source demo_tls_source { tcp( ip(0.0.0.0) port(1999) tls( key_file('/opt/syslog-ng/etc/syslog-ng/key.d/syslog-ng.key') cert_file('/opt/syslog-ng/etc/syslog-ng/cert.d/syslog-ng.cert') ) ); }; Does not need examples. """ def __init__(self, type="", arguments=None): super().__init__(arguments, "\n") self.type = type self.arguments = arguments if arguments else [] self.iterable = self.arguments def build(self): header = _indentln(f"{self.type}(") tail = _indent(")") body = self.build_body() return header + body + tail def add_argument(self, arg): self.arguments.append(arg) class Argument: """ A TypedParameterValue has one or more Arguments. For example this can be the value of key_file. Does not need examples. """ def __init__(self, value=""): self.value = value def build(self): return _indent(self.value) def _is_statement_unnamed(statement): """ Returns True, if the given statement is an unnamed statement, like log or junction. """ return statement in ("log", "channel", "junction", "options") def _is_simple_type(value): """ Returns True, if the given parameter value is an instance of either int, str, float or bool. """ return ( isinstance(value, str) or isinstance(value, int) or isinstance(value, float) or isinstance(value, bool) ) def _get_type_id_options(name, configuration): """ Returns the type, id and option of a configuration object. """ # it's in a form of source.name if "." in name: type_, sep, id_ = name.partition(".") options = configuration else: type_ = next(iter(configuration.keys())) id_ = name options = configuration[type_] return type_, id_, options def _expand_one_key_dictionary(_dict): """ Returns the only one key and its value from a dictionary. """ key = next(iter(_dict.keys())) value = _dict[key] return key, value def _parse_typed_parameter_typed_value(values): """ Creates Arguments in a TypedParametervalue. """ type_, value = _expand_one_key_dictionary(values) _current_parameter_value.type = type_ if _is_simple_type(value): arg = Argument(value) _current_parameter_value.add_argument(arg) elif isinstance(value, list): for idx in value: arg = Argument(idx) _current_parameter_value.add_argument(arg) def _parse_typed_parameter(param): """ Parses a TypedParameter and fills it with values. """ global _current_parameter_value type_, value = _expand_one_key_dictionary(param) _current_parameter.type = type_ if _is_simple_type(value) and value != "": _current_parameter_value = SimpleParameterValue(value) _current_parameter.add_value(_current_parameter_value) elif isinstance(value, list): for i in value: if _is_simple_type(i): _current_parameter_value = SimpleParameterValue(i) _current_parameter.add_value(_current_parameter_value) elif isinstance(i, dict): _current_parameter_value = TypedParameterValue() _parse_typed_parameter_typed_value(i) _current_parameter.add_value(_current_parameter_value) def _create_and_add_parameters(params): """ Parses the configuration and creates Parameter instances. """ global _current_parameter if _is_simple_type(params): _current_parameter = SimpleParameter(params) _current_option.add_parameter(_current_parameter) else: # must be a list for i in params: if _is_simple_type(i): _current_parameter = SimpleParameter(i) else: _current_parameter = TypedParameter() _parse_typed_parameter(i) _current_option.add_parameter(_current_parameter) def _create_and_add_option(option): """ Parses the configuration and creates an Option instance. """ global _current_option _current_option = Option() type_, params = _expand_one_key_dictionary(option) _current_option.type = type_ _create_and_add_parameters(params) _current_statement.add_child(_current_option) def _parse_statement(options): """ Parses the configuration and creates options the statement. """ for option in options: _create_and_add_option(option) def _is_reference(arg): """ Return True, if arg is a reference to a previously defined statement. """ return ( isinstance(arg, dict) and len(arg) == 1 and isinstance(next(iter(arg.values())), str) ) def _is_junction(arg): """ Return True, if arg is a junction statement. """ return ( isinstance(arg, dict) and len(arg) == 1 and next(iter(arg.keys())) == "junction" ) def _add_reference(reference, statement): """ Adds a reference to statement. """ type_, value = _expand_one_key_dictionary(reference) opt = Option(type_) param = SimpleParameter(value) opt.add_parameter(param) statement.add_child(opt) def _is_inline_definition(arg): """ Returns True, if arg is an inline definition of a statement. """ return ( isinstance(arg, dict) and len(arg) == 1 and isinstance(next(iter(arg.values())), list) ) def _add_inline_definition(item, statement): """ Adds an inline definition to statement. """ global _current_statement backup = _current_statement type_, options = _expand_one_key_dictionary(item) _current_statement = UnnamedStatement(type=type_) _parse_statement(options) statement.add_child(_current_statement) _current_statement = backup def _add_junction(item): """ Adds a junction to the _current_statement. """ type_, channels = _expand_one_key_dictionary(item) junction = UnnamedStatement(type="junction") for item in channels: type_, value = _expand_one_key_dictionary(item) channel = UnnamedStatement(type="channel") for val in value: if _is_reference(val): _add_reference(val, channel) elif _is_inline_definition(val): _add_inline_definition(val, channel) junction.add_child(channel) _current_statement.add_child(junction) def _parse_log_statement(options): """ Parses a log path. """ for i in options: if _is_reference(i): _add_reference(i, _current_statement) elif _is_junction(i): _add_junction(i) elif _is_inline_definition(i): _add_inline_definition(i, _current_statement) def _build_config_tree(name, configuration): """ Build the configuration tree. The root object is _current_statement. """ type_, id_, options = _get_type_id_options(name, configuration) global _INDENT, _current_statement _INDENT = "" if type_ == "config": _current_statement = GivenStatement(options) elif type_ == "log": _current_statement = UnnamedStatement(type="log") _parse_log_statement(options) else: if _is_statement_unnamed(type_): _current_statement = UnnamedStatement(type=type_) else: _current_statement = NamedStatement(type=type_, id=id_) _parse_statement(options) def _render_configuration(): """ Renders the configuration tree into syslog-ng's configuration syntax. """ text_repr = _current_statement.build() _INDENT = "" return text_repr def config(name, config, write=True): """ Builds syslog-ng configuration. This function is intended to be used from the state module, users should not use it directly! name : the id of the Salt document or it is the format of <statement name>.id config : the parsed YAML code write : if True, it writes the config into the configuration file, otherwise just returns it CLI Example: .. code-block:: bash salt '*' syslog_ng.config name='s_local' config="[{'tcp':[{'ip':'127.0.0.1'},{'port':1233}]}]" """ _build_config_tree(name, config) configs = _render_configuration() if __opts__.get("test", False): comment = "State syslog_ng will write '{}' into {}".format( configs, __SYSLOG_NG_CONFIG_FILE ) return _format_state_result(name, result=None, comment=comment) succ = write if write: succ = _write_config(config=configs) return _format_state_result(name, result=succ, changes={"new": configs, "old": ""}) def set_binary_path(name): """ Sets the path, where the syslog-ng binary can be found. This function is intended to be used from states. If syslog-ng is installed via a package manager, users don't need to use this function. CLI Example: .. code-block:: bash salt '*' syslog_ng.set_binary_path name=/usr/sbin """ global __SYSLOG_NG_BINARY_PATH old = __SYSLOG_NG_BINARY_PATH __SYSLOG_NG_BINARY_PATH = name changes = _format_changes(old, name) return _format_state_result(name, result=True, changes=changes) def set_config_file(name): """ Sets the configuration's name. This function is intended to be used from states. CLI Example: .. code-block:: bash salt '*' syslog_ng.set_config_file name=/etc/syslog-ng """ global __SYSLOG_NG_CONFIG_FILE old = __SYSLOG_NG_CONFIG_FILE __SYSLOG_NG_CONFIG_FILE = name changes = _format_changes(old, name) return _format_state_result(name, result=True, changes=changes) def get_config_file(): """ Returns the configuration directory, which contains syslog-ng.conf. CLI Example: .. code-block:: bash salt '*' syslog_ng.get_config_file """ return __SYSLOG_NG_CONFIG_FILE def _run_command(cmd, options=(), env=None): """ Runs the command cmd with options as its CLI parameters and returns the result as a dictionary. """ params = [cmd] params.extend(options) return __salt__["cmd.run_all"](params, env=env, python_shell=False) def _determine_config_version(syslog_ng_sbin_dir): ret = version(syslog_ng_sbin_dir) full_version = ret["stdout"] dot_count = 0 for idx, part in enumerate(full_version): if part == ".": dot_count = dot_count + 1 if dot_count == 2: return full_version[0:idx] # return first 3 characters return full_version[:3] def set_parameters(version=None, binary_path=None, config_file=None, *args, **kwargs): """ Sets variables. CLI Example: .. code-block:: bash salt '*' syslog_ng.set_parameters version='3.6' salt '*' syslog_ng.set_parameters binary_path=/home/user/install/syslog-ng/sbin config_file=/home/user/install/syslog-ng/etc/syslog-ng.conf """ if binary_path: set_binary_path(binary_path) if config_file: set_config_file(config_file) if version: version = _determine_config_version(__SYSLOG_NG_BINARY_PATH) write_version(version) return _format_return_data(0) def _run_command_in_extended_path(syslog_ng_sbin_dir, command, params): """ Runs the specified command with the syslog_ng_sbin_dir in the PATH """ orig_path = os.environ.get("PATH", "") env = None if syslog_ng_sbin_dir: # Custom environment variables should be str types. This code # normalizes the paths to unicode to join them together, and then # converts back to a str type. env = { "PATH": salt.utils.stringutils.to_str( os.pathsep.join(salt.utils.data.decode((orig_path, syslog_ng_sbin_dir))) ) } return _run_command(command, options=params, env=env) def _format_return_data(retcode, stdout=None, stderr=None): """ Creates a dictionary from the parameters, which can be used to return data to Salt. """ ret = {"retcode": retcode} if stdout is not None: ret["stdout"] = stdout if stderr is not None: ret["stderr"] = stderr return ret def config_test(syslog_ng_sbin_dir=None, cfgfile=None): """ Runs syntax check against cfgfile. If syslog_ng_sbin_dir is specified, it is added to the PATH during the test. CLI Example: .. code-block:: bash salt '*' syslog_ng.config_test salt '*' syslog_ng.config_test /home/user/install/syslog-ng/sbin salt '*' syslog_ng.config_test /home/user/install/syslog-ng/sbin /etc/syslog-ng/syslog-ng.conf """ params = ["--syntax-only"] if cfgfile: params.append(f"--cfgfile={cfgfile}") try: ret = _run_command_in_extended_path(syslog_ng_sbin_dir, "syslog-ng", params) except CommandExecutionError as err: return _format_return_data(retcode=-1, stderr=str(err)) retcode = ret.get("retcode", -1) stderr = ret.get("stderr", None) stdout = ret.get("stdout", None) return _format_return_data(retcode, stdout, stderr) def version(syslog_ng_sbin_dir=None): """ Returns the version of the installed syslog-ng. If syslog_ng_sbin_dir is specified, it is added to the PATH during the execution of the command syslog-ng. CLI Example: .. code-block:: bash salt '*' syslog_ng.version salt '*' syslog_ng.version /home/user/install/syslog-ng/sbin """ try: ret = _run_command_in_extended_path(syslog_ng_sbin_dir, "syslog-ng", ("-V",)) except CommandExecutionError as err: return _format_return_data(retcode=-1, stderr=str(err)) if ret["retcode"] != 0: return _format_return_data( ret["retcode"], stderr=ret["stderr"], stdout=ret["stdout"] ) lines = ret["stdout"].split("\n") # The format of the first line in the output is: # syslog-ng 3.6.0alpha0 version_line_index = 0 version_column_index = 1 line = lines[version_line_index].split()[version_column_index] return _format_return_data(0, stdout=line) def modules(syslog_ng_sbin_dir=None): """ Returns the available modules. If syslog_ng_sbin_dir is specified, it is added to the PATH during the execution of the command syslog-ng. CLI Example: .. code-block:: bash salt '*' syslog_ng.modules salt '*' syslog_ng.modules /home/user/install/syslog-ng/sbin """ try: ret = _run_command_in_extended_path(syslog_ng_sbin_dir, "syslog-ng", ("-V",)) except CommandExecutionError as err: return _format_return_data(retcode=-1, stderr=str(err)) if ret["retcode"] != 0: return _format_return_data(ret["retcode"], ret.get("stdout"), ret.get("stderr")) lines = ret["stdout"].split("\n") for line in lines: if line.startswith("Available-Modules"): label, installed_modules = line.split() return _format_return_data(ret["retcode"], stdout=installed_modules) return _format_return_data(-1, stderr="Unable to find the modules.") def stats(syslog_ng_sbin_dir=None): """ Returns statistics from the running syslog-ng instance. If syslog_ng_sbin_dir is specified, it is added to the PATH during the execution of the command syslog-ng-ctl. CLI Example: .. code-block:: bash salt '*' syslog_ng.stats salt '*' syslog_ng.stats /home/user/install/syslog-ng/sbin """ try: ret = _run_command_in_extended_path( syslog_ng_sbin_dir, "syslog-ng-ctl", ("stats",) ) except CommandExecutionError as err: return _format_return_data(retcode=-1, stderr=str(err)) return _format_return_data(ret["retcode"], ret.get("stdout"), ret.get("stderr")) def _format_changes(old="", new=""): return {"old": old, "new": new} def _format_state_result(name, result, changes=None, comment=""): """ Creates the state result dictionary. """ if changes is None: changes = {"old": "", "new": ""} return {"name": name, "result": result, "changes": changes, "comment": comment} def _add_cli_param(params, key, value): """ Adds key and value as a command line parameter to params. """ if value is not None: params.append(f"--{key}={value}") def _add_boolean_cli_param(params, key, value): """ Adds key as a command line parameter to params. """ if value is True: params.append(f"--{key}") def stop(name=None): """ Kills syslog-ng. This function is intended to be used from the state module. Users shouldn't use this function, if the service module is available on their system. If :mod:`syslog_ng.set_config_file <salt.modules.syslog_ng.set_binary_path>` is called before, this function will use the set binary path. CLI Example: .. code-block:: bash salt '*' syslog_ng.stop """ pids = __salt__["ps.pgrep"](pattern="syslog-ng") if not pids: return _format_state_result( name, result=False, comment="Syslog-ng is not running" ) if __opts__.get("test", False): comment = "Syslog_ng state module will kill {0} pids" return _format_state_result(name, result=None, comment=comment) res = __salt__["ps.pkill"]("syslog-ng") killed_pids = res["killed"] if killed_pids == pids: changes = {"old": killed_pids, "new": []} return _format_state_result(name, result=True, changes=changes) else: return _format_state_result(name, result=False) def start( name=None, user=None, group=None, chroot=None, caps=None, no_caps=False, pidfile=None, enable_core=False, fd_limit=None, verbose=False, debug=False, trace=False, yydebug=False, persist_file=None, control=None, worker_threads=None, ): """ Ensures, that syslog-ng is started via the given parameters. This function is intended to be used from the state module. Users shouldn't use this function, if the service module is available on their system. If :mod:`syslog_ng.set_config_file <salt.modules.syslog_ng.set_binary_path>`, is called before, this function will use the set binary path. CLI Example: .. code-block:: bash salt '*' syslog_ng.start """ params = [] _add_cli_param(params, "user", user) _add_cli_param(params, "group", group) _add_cli_param(params, "chroot", chroot) _add_cli_param(params, "caps", caps) _add_boolean_cli_param(params, "no-capse", no_caps) _add_cli_param(params, "pidfile", pidfile) _add_boolean_cli_param(params, "enable-core", enable_core) _add_cli_param(params, "fd-limit", fd_limit) _add_boolean_cli_param(params, "verbose", verbose) _add_boolean_cli_param(params, "debug", debug) _add_boolean_cli_param(params, "trace", trace) _add_boolean_cli_param(params, "yydebug", yydebug) _add_cli_param(params, "cfgfile", __SYSLOG_NG_CONFIG_FILE) _add_boolean_cli_param(params, "persist-file", persist_file) _add_cli_param(params, "control", control) _add_cli_param(params, "worker-threads", worker_threads) if __SYSLOG_NG_BINARY_PATH: syslog_ng_binary = os.path.join(__SYSLOG_NG_BINARY_PATH, "syslog-ng") command = [syslog_ng_binary] + params if __opts__.get("test", False): comment = f"Syslog_ng state module will start {command}" return _format_state_result(name, result=None, comment=comment) result = __salt__["cmd.run_all"](command, python_shell=False) else: command = ["syslog-ng"] + params if __opts__.get("test", False): comment = f"Syslog_ng state module will start {command}" return _format_state_result(name, result=None, comment=comment) result = __salt__["cmd.run_all"](command, python_shell=False) if result["pid"] > 0: succ = True else: succ = False return _format_state_result( name, result=succ, changes={"new": " ".join(command), "old": ""} ) def reload_(name): """ Reloads syslog-ng. This function is intended to be used from states. If :mod:`syslog_ng.set_config_file <salt.modules.syslog_ng.set_binary_path>`, is called before, this function will use the set binary path. CLI Example: .. code-block:: bash salt '*' syslog_ng.reload """ if __SYSLOG_NG_BINARY_PATH: syslog_ng_ctl_binary = os.path.join(__SYSLOG_NG_BINARY_PATH, "syslog-ng-ctl") command = [syslog_ng_ctl_binary, "reload"] result = __salt__["cmd.run_all"](command, python_shell=False) else: command = ["syslog-ng-ctl", "reload"] result = __salt__["cmd.run_all"](command, python_shell=False) succ = True if result["retcode"] == 0 else False return _format_state_result(name, result=succ, comment=result["stdout"]) def _format_generated_config_header(): """ Formats a header, which is prepended to all appended config. """ now = time.strftime("%Y-%m-%d %H:%M:%S") return __SALT_GENERATED_CONFIG_HEADER.format(now) def write_config(config, newlines=2): """ Writes the given parameter config into the config file. This function is intended to be used from states. If :mod:`syslog_ng.set_config_file <salt.modules.syslog_ng.set_config_file>`, is called before, this function will use the set config file. CLI Example: .. code-block:: bash salt '*' syslog_ng.write_config config='# comment' """ succ = _write_config(config, newlines) changes = _format_changes(new=config) return _format_state_result(name="", result=succ, changes=changes) def _write_config(config, newlines=2): """ Writes the given parameter config into the config file. """ text = config if isinstance(config, dict) and len(list(list(config.keys()))) == 1: key = next(iter(config.keys())) text = config[key] try: with salt.utils.files.fopen(__SYSLOG_NG_CONFIG_FILE, "a") as fha: fha.write(salt.utils.stringutils.to_str(text)) for _ in range(0, newlines): fha.write(salt.utils.stringutils.to_str(os.linesep)) return True except Exception as err: # pylint: disable=broad-except log.error(str(err)) return False def write_version(name): """ Removes the previous configuration file, then creates a new one and writes the name line. This function is intended to be used from states. If :mod:`syslog_ng.set_config_file <salt.modules.syslog_ng.set_config_file>`, is called before, this function will use the set config file. CLI Example: .. code-block:: bash salt '*' syslog_ng.write_version name="3.6" """ line = f"@version: {name}" try: if os.path.exists(__SYSLOG_NG_CONFIG_FILE): log.debug( "Removing previous configuration file: %s", __SYSLOG_NG_CONFIG_FILE ) os.remove(__SYSLOG_NG_CONFIG_FILE) log.debug("Configuration file successfully removed") header = _format_generated_config_header() _write_config(config=header, newlines=1) _write_config(config=line, newlines=2) return _format_state_result(name, result=True) except OSError as err: log.error( "Failed to remove previous configuration file '%s': %s", __SYSLOG_NG_CONFIG_FILE, err, ) return _format_state_result(name, result=False)