Esempio n. 1
0
    def new():
        """
        Select our event input based on the `EVENT_SOURCE` environment variable setting.  `EVENT_SOURCE` can currently
        have one of a these settings:

            * ``commandline``: accept a single event as a string on the `docker` command line
            * ``environment``: Read a single event from the `AWS_LAMBDA_EVENT_BODY` environment variable
            * ``filesystem``: Read one or more events from a folder in the Docker filesystem; either built
               in to the image or mounted through a volume mount
            * ``kinesis``: read events from a Kinesis stream, or from a kinesalite stream

        :rtype: an event source class
        """
        source = os.environ.get('EVENT_SOURCE', 'commandline')
        if source not in [
                'filesystem', 'kinesis', 'environment', 'commandline'
        ]:
            eprint('docker-lambda.source.unknown source=%s' % source)
            sys.exit(1)
        else:
            log('docker-lambda.source.selected source=%s' % source)
        if source == 'filesystem':
            source = FilesystemEventSource()
        elif source == 'kinesis':
            source = KinesisEventSource()
        elif source == 'environment':
            source = EnvironmentEventSource()
        elif source == 'commandline':
            source = CommandLineEventSource()
        return source
Esempio n. 2
0
 def poll(self):
     if len(sys.argv) > 2:
         event = sys.argv[2]
     else:
         log("docker-lambda.source.commandline.no-event")
         event = "{}"
     self.is_done = True
     return event
Esempio n. 3
0
 def poll(self):
     if len(self.files) > 0:
         if self.index < len(self.files):
             with open(self.files[self.index], 'r') as fd:
                 events = fd.read()
             log("docker-lambda.source.filesystem.done.event-loaded folder=%s file=%s"
                 % (self.folder_name, self.files[self.index]))
             self.index += 1
             if self.index >= len(self.files):
                 if self.loop:
                     self.index = 0
                     log("docker-lambda.source.filesystem.done.rewind folder=%s loop=%s"
                         % (self.folder_name, self.loop))
                 else:
                     log("docker-lambda.source.filesystem.done.no-more-files "
                         "folder=%s loop=%s exit-policy=%s" %
                         (self.folder_name, self.loop, self.exit_policy))
                     if self.exit_policy == "wait":
                         while True:
                             time.sleep(30)
                     else:
                         log("docker-lambda.source.filesystem.done")
                         self.is_done = True
     else:
         eprint("docker-lambda.source.filesystem.error.no-files folder=%s" %
                self.folder_name)
         sys.exit(1)
     time.sleep(self.period)
     return events
Esempio n. 4
0
 def __init__(self):
     self.folder_name = os.environ['FILESYSTEM_FOLDER']
     self.period = int(os.environ.get('FILESYSTEM_SLEEP_SECONDS', 1))
     self.loop = os.environ.get('FILESYSTEM_LOOP', "False") == "True"
     # Either "exit" or "wait"
     self.exit_policy = os.environ.get('FILESYSTEM_EXIT_POLICY', "exit")
     self.files = [
         os.path.join(self.folder_name, f)
         for f in os.listdir(self.folder_name)
         if os.path.isfile(os.path.join(self.folder_name, f))
     ]
     self.files.sort()
     self.index = 0
     log("docker-lambda.source.filesystem.start folder=%s files=%s loop=%s period=%s"
         % (self.folder_name, len(self.files), self.loop, self.period))
     self.is_done = False
Esempio n. 5
0
    def poll(self):
        """
        This is what receive_invoke() calls.  This will block until records are available, return all records found and
        go back to waiting for records.
        """
        while 1:
            records = self.kinesis.get_records(ShardIterator=self.shard_iterator['ShardIterator'])
            if len(records['Records']) > 0:
                break
            log(
                "docker-lambda.source.kinesis.stream.poll.no-events stream_name=%s" % (self.stream_name)
            )
            # For standard iterators, Lambda polls each shard in your Kinesis stream for records at a base rate of once
            # per second.  When more records are available, Lambda keeps processing batches until it receives a batch
            # that's smaller than the configured maximum batch size. The function shares read throughput with other
            # consumers of the shard.
            # Ref: https://docs.aws.amazon.com/lambda/latest/dg/with-kinesis.html
            time.sleep(1)

        events = {'Records': []}
        for krecord in records['Records']:
            events['Records'].append({
                "kinesis": {
                    "kinesisSchemaVersion": "1.0",
                    "partitionKey": "1",
                    "sequenceNumber": krecord['SequenceNumber'],
                    "data": b64encode(krecord['Data']).decode(),
                    "approximateArrivalTimestamp": krecord['ApproximateArrivalTimestamp'].timestamp()
                },
                "eventSource": "aws:kinesis",
                "eventVersion": "1.0",
                "eventID": f"{self.shard_id}:{krecord['SequenceNumber']}",
                "eventName": "aws:kinesis:record",
                "invokeIdentityArn": "my_fake_arn",
                "awsRegion": self.region,
                "eventSourceARN": self.stream_arn
            })

        log(
            "docker-lambda.source.kinesis.stream.poll stream_name=%s nevents=%s" % (self.stream_name, len(events['Records']))
        )
        return json.dumps(events).encode('utf8')
Esempio n. 6
0
 def __init__(self):
     self.stream_name = os.environ['KINESIS_STREAM_NAME']
     self.region = os.environ.get('AWS_REGION', os.environ.get('AWS_DEFAULT_REGION', 'us-east-1'))
     access_key_id = os.environ.get('AWS_ACCESS_KEY_ID', 'SOME_ACCESS_KEY_ID')
     secret_access_key = os.environ.get('AWS_SECRET_ACCESS_KEY', 'SOME_SECRET_ACCESS_KEY')
     endpoint_url = os.environ.get('KINESIS_ENDPOINT_URL', None)
     log("docker-lambda.source.kinesis.start stream_name=%s %s" % (
         self.stream_name,
         "endpoint_url=%s" % endpoint_url if endpoint_url else ''
     ))
     self.kinesis = boto3.client(
         'kinesis',
         aws_access_key_id=access_key_id,
         aws_secret_access_key=secret_access_key,
         region_name=self.region,
         endpoint_url=os.environ.get('KINESIS_ENDPOINT_URL', None)
     )
     waiter = self.kinesis.get_waiter('stream_exists')
     started = False
     count = 0
     while not started:
         try:
             waiter.wait(StreamName=self.stream_name)
         except botocore.exceptions.WaiterError:
             # If we're using a Kinesalite container, it may take a little while for it to
             # boot and create its stream.  Give it a
             log("docker-lambda.source.kinesis.stream.not-ready stream_name=%s")
             time.sleep(2)
             count += 1
             if count == 10:
                 raise
         else:
             started = True
     stream = self.kinesis.describe_stream(StreamName=self.stream_name)
     self.stream_arn = stream['StreamDescription']['StreamARN']
     shards = self.kinesis.list_shards(StreamName=self.stream_name)
     self.shard_id = shards['Shards'][0]['ShardId']
     self.shard_iterator = self.kinesis.get_shard_iterator(
         StreamName=self.stream_name,
         ShardId=self.shard_id,
         ShardIteratorType='LATEST'
     )
     log("docker-lambda.source.kinesis.stream.ready stream_name=%s" % self.stream_name)
Esempio n. 7
0
 def done(self):
     if self.is_done:
         log("docker-lambda.source.environment.done")
     return self.is_done
Esempio n. 8
0
 def poll(self):
     event = os.environ.get('AWS_LAMBDA_EVENT_BODY', {})
     if not event:
         log("docker-lambda.source.environment.no-event")
     self.is_done = True
     return event
Esempio n. 9
0
 def done(self):
     if self.is_done:
         log("docker-lambda.source.commandline.done")
     return self.is_done