---
meta:
    description:
        Processes events in a Kinesis stream

    parameters:
        has_dead_letter_queue:
            description: If set to false a DLQ will not be created if a queue ARN is not provided
            value: yes

        dead_letter_queue_arn:
            description: ARN of the Dead Letter Queue
            value:

        async_batch_size:
            description: A custom batch size for async invocations
            value:

        async:
            description: Should execution be async? yes or no
            value: no

        logging_level:
            description: The logging level
            value: INFO

        runtime:
            description: The Python runtime. Either python2.7 or python3.6.
            value: "python3.6"

        received_at_field:
            description:
                The name of the field where the arrival timestamp will be embedded
            value:
                # This naming convention makes sense if using Polku's client SDKs
                receivedAt

        logs_destination_arn:
            description:
                The ARN of a Kinesis stream or Lambda function to where
                Cloudwatch logs will be delivered.
            value:

        logs_filter_pattern:
            description:
                The filter pattern for the logs delivered to the logs destination
            value: ERROR

        sns_topic:
            description:
                The SNS topic where alarm notifications will be posted. This
                can be either an ARN of an existing topic, or the name of a
                topic to be created during the creation of this layer.
            value:
                {{_env.name}}-{{_env.stage}}-{{_layer.name}}

        alert_subscribers:
            description:
                A list of emails to suscribe to the alarms that will be pushed
                to the sns topic of this environment
            value:
                []

        invocation_duration_alarm:
            description:
                Alarm when invocation duration is above expecations.
            value:
                statistic: Average
                period: 300
                evaluation_periods: 1
                threshold: 120

        invocation_errors_alarm:
            description:
                Alarm when there are too many invocation errors
            value:
                statistic: Sum
                period: 300
                evaluation_periods: 1
                threshold: 5

        invocations_alarm:
            description:
                Alarm when there are too many or too few invocations
            value:
                statistic: Sum
                period: 300
                evaluation_periods: 2
                upper_threshold: 1000
                lower_threshold: 5

        variables:
            description:
                Environment variables to pass to the Lambda
            value: {}

        dynamodb_capacity:
            description:
                The read and write capacity for the Lambda state table(s)
            value:
                read: 5
                write: 5

        memory_size:
            description:
                The amount of memory in MB allocated to the Lambda function
            value:
                128

        timeout:
            description:
                The timeout execution time, in seconds
            value:
                100

        starting_position:
            description:
                The starting position in the Kinesis stream
            value:
                TRIM_HORIZON

        batch_size:
            description:
                The number of events to batch in one lambda execution
            value: 1

        lambda_dependencies:
            description:
                A list of Python dependencies for the Lambda function
            value: []

        iam_actions:
            description:
                Additional IAM actions that the Lambda will be allowed to perform
            value: []   # A list of dicts like {action: x, resource: y}

        kms_key_admins:
            description: List of IAM users that are allowed to administer the key
            value: []

        kms_key_users:
            description: List of IAM users that are allowed to administer the key
            value: []

        kinesis_deserializer:
            description: A callable used to deserialize records in a Kinesis stream
            value: json.loads

        kinesis_serializer:
            description: A callable used to serialize records before sending
                         them to Kinesis
            value: json.dumps

        kinesis_unpacker:
            description: A callable used to unpack records in a Kinesis stream
                         For example, it could be gzip.decompress.
            value:

        kinesis_packer:
            description: A callable used to process searialized records before
                         sending them to Kinesis. For example, it could be
                         gzip.compress.
            value:

        # There can be 0 or 1 input/error streams
        {% set stream = {"input": input, "error": error} %}
        {% for stype in ["input", "error"] %}
        {% set s = stream[stype] %}
        {% if s %}
        meta_{{stype}}:
            description:
                Settings for the {{stype}} event stream
            value:
                {% if s.kinesis_stream %}
                kinesis_stream:
                    {% if s.kinesis_stream is mapping and 'layer' in s.kinesis_stream %}
                    {# if user is passing a reference to a layer output #}
                    ref:
                        parser: output
                        parameters:
                            layer_name: {{s.kinesis_stream.layer}}
                            output_name: {{s.kinesis_stream.name}}
                    {% else %}
                    {# else assume user is passing the name of the stream #}
                    {{s.kinesis_stream}}
                    {% endif %}
                {% endif %}
                {% if s.firehose_delivery_stream %}
                firehose_delivery_stream:
                    {% if s.firehose_delivery_stream is mapping and 'layer' in s.firehose_delivery_stream %}
                    - stream_name:
                        ref:
                            parser: output
                            parameters:
                                layer_name: {{s.firehose_delivery_stream.layer}}
                                output_name: {{s.firehose_delivery_stream.name}}
                      {% if s.firehose_delivery_stream.filter %}
                      filter: {{s.firehose_delivery_stream.filter}}
                      {% endif %}
                      {% if s.firehose_delivery_stream.mapper %}
                      mapper: {{s.firehose_delivery_stream.mapper}}
                      {% endif %}
                    {% elif s.firehose_delivery_stream|is_list %}
                    {% for ds in s.firehose_delivery_stream %}
                    {% if ds is mapping and 'layer' in ds %}
                    - stream_name:
                        ref:
                            parser: output
                            parameters:
                                layer_name: {{ds.layer}}
                                output_name: {{ds.name}}
                      {% if ds.filter %}
                      filter: {{ds.filter}}
                      {% endif %}
                      {% if ds.mapper %}
                      mapper: {{ds.mapper}}
                      {% endif %}
                    {% else %}
                    - stream_name: {{ds}}
                    {% endif %}
                    {% endfor %}
                    {% else %}
                    # user is passing directly the name of the delivery stream
                    - stream_name: {{s.firehose_delivery_stream}}
                    {% endif %}
                {% endif %}
                mapper: "{{s.mapper}}"
                filter: "{{s.filter}}"
                batch_mapper: "{{s.batch_mapper}}"
        {% endif %}
        {% endfor %}

        # There can be 0 or more output streams
        {% if output %}
        meta_output:
            description:
                Settings for the output event stream(s)
            value:
                {% for s in output %}
                - mapper: "{{s.mapper}}"
                  filter: "{{s.filter}}"
                  partition_key: {{s.partition_key}}
                  {% if s.kinesis_stream %}
                  kinesis_stream:
                      {% if s.kinesis_stream is mapping and 'layer' in s.kinesis_stream %}
                      {# user is passing a reference to another layer output #}
                      ref:
                          parser: output
                          parameters:
                              layer_name: {{s.kinesis_stream.layer}}
                              output_name: {{s.kinesis_stream.name}}
                      {% else %}
                      {# user is passing directly the name of the stream #}
                      {{s.kinesis_stream}}
                      {% endif %}
                  {% endif %}
                  {% if s.firehose_delivery_stream %}
                  firehose_delivery_stream:
                      {% if s.firehose_delivery_stream is mapping and 'layer' in s.firehose_delivery_stream %}
                      - stream_name:
                          ref:
                              parser: output
                              parameters:
                                  layer_name: {{s.firehose_delivery_stream.layer}}
                                  output_name: {{s.firehose_delivery_stream.name}}
                        {% if s.firehose_delivery_stream.filter %}
                        filter: {{s.firehose_delivery_stream.filter}}
                        {% endif %}
                        {% if s.firehose_delivery_stream.mapper %}
                        mapper: {{s.firehose_delivery_stream.mapper}}
                        {% endif %}
                      {% elif s.firehose_delivery_stream|is_list %}
                      {% for ds in s.firehose_delivery_stream %}
                      {% if ds is mapping and 'layer' in ds %}
                      - stream_name:
                          ref:
                              parser: output
                              parameters:
                                  layer_name: {{ds.layer}}
                                  output_name: {{ds.name}}
                        {% if ds.filter %}
                        filter: {{ds.filter}}
                        {% endif %}
                        {% if ds.mapper %}
                        mapper: {{ds.mapper}}
                        {% endif %}
                      {% else %}
                      - stream_name: {{ds}}
                      {% endif %}
                      {% endfor %}
                      {% else %}
                      # user is passing directly the name of the delivery stream
                      - stream_name: {{s.firehose_delivery_stream}}
                      {% endif %}
                  {% endif %}
                {% endfor %}
        {% endif %}

        lambda_function:
            # We use a low priority so that the references above that retrieve
            # the names of the relevant streams are resolved before this
            # reference.
            priority: 100
            value:
                ref:
                    parser: lambda
                    parameters:
                        path: lambda_function
                        dependencies: {{lambda_dependencies or []}}
