{%- from "rsyslog/map.jinja" import global with context -%}

{% for modname in global.modules -%}
$ModLoad {{ modname }}
{% endfor -%}
{% if global.preserve_fqdn == true -%}
$PreserveFQDN on
{% else -%}
$PreserveFQDN off
{% endif -%}
{% if global.non_kernel_facility is defined and global.non_kernel_facility == true -%}
$KLogPermitNonKernelFacility on
{% endif -%}
{% if global.omit_local_logging is defined and global.omit_local_logging == true -%}
$OmitLocalLogging on
{% endif -%}
{% if global.msg_reduction == true -%}
$RepeatedMsgReduction on
{% endif -%}
{% if global.max_message_size is defined -%}
$MaxMessageSize {{ global.max_message_size }}
{% endif -%}
{% if global.system_log_rate_limit_interval is defined -%}
$SystemLogRateLimitInterval {{ global.system_log_rate_limit_interval }}
{% endif -%}
{% if global.system_log_rateLimit_burst is defined -%}
$SystemLogRateLimitBurst {{ global.system_log_rateLimit_burst }}
{% endif -%}
$DirCreateMode {{ global.perm_dir }}
$PrivDropToUser {{ global.run_user }}
$PrivDropToGroup {{ global.run_group }}
$WorkDirectory {{ global.spool_dir }}

{% if global.format is defined -%}
$Template {{ global.format.name }}, "{{ global.format.template }}"
$ActionFileDefaultTemplate {{ global.format.name }}
{% else -%}
$template RSYSLOG_TraditionalFileFormat
$ActionFileDefaultTemplate RSYSLOG_TraditionalFileFormat
{% endif -%}

{# Additional configurations should be included after defining the global format otherwise they won't benefit from it #}
$IncludeConfig {{ global.rsyslog_d }}/*.conf

{%- set file_groups = {
  'stop': {},
  'other': {}
} -%}

{%- for name,config in global.output.file.iteritems() if config.get('enabled', False) %}
{%- if config.get('stop_processing', False) -%}
{%- do file_groups.stop.update({name: config}) -%}
{%- else -%}
{%- do file_groups.other.update({name: config}) -%}
{%- endif -%}
{%- if config.template is defined %}
$Template {{ name|replace('/', '_') }}, "{{ config.template }}"
{%- endif -%}
{%- endfor -%}

{%- macro rsyslog_output_file(files) -%}
{%- for name, config in files.items() %}
{% if config.owner is defined -%}
$FileOwner {{ config['owner'] }}
{% endif -%}
{% if config.group is defined -%}
$FileGroup {{ config['group'] }}
{% endif -%}
{% if config.createmode is defined -%}
$FileCreateMode {{ config['createmode'] }}
{% endif -%}
{% if config.umask is defined -%}
$Umask {{ config['umask'] }}
{% endif -%}
{{ config['filter'] }}     {% if config.sync == true %}-{% endif %}{{ name }}{%if config.template is defined %};{{ name|replace('/', '_') }}{% endif %}
{%- if config.get('stop_processing', False) %}
&stop
{%- endif %}
{% endfor -%}
{%- endmacro %}

{{ rsyslog_output_file(file_groups.stop) }}
{{ rsyslog_output_file(file_groups.other) }}

{% if global.output.console is defined %}
{% for name,config in global.output.console.iteritems() if config.get('enabled', False) -%}
{{ config['filter'] }}      {{ config['action'] }}
{% endfor -%}
{% endif -%}

{% if global.output.remote is defined %}
{% for name,config in global.output.remote.iteritems() if config.get('enabled', False) -%}
{{ config['filter'] }}      {{ config['action'] }}
{% endfor -%}
{% endif -%}
