Skip to content

Commit f8ed841

Browse files
committed
Implement xp lambda run [Handler] to run lambdas locally
1 parent cf29cc7 commit f8ed841

File tree

2 files changed

+78
-12
lines changed

2 files changed

+78
-12
lines changed
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
<?php namespace xp\lambda;
2+
3+
use com\amazon\aws\lambda\{Environment, Context};
4+
use lang\{XPClass, Throwable};
5+
use util\UUID;
6+
use util\cmd\Console;
7+
8+
/**
9+
* Run lambdas locally
10+
*
11+
* @see https://docs.aws.amazon.com/de_de/lambda/latest/dg/runtimes-api.html
12+
*/
13+
class RunLambda {
14+
const TRACE_ID= 'Root=1-5bef4de7-ad49b0e87f6ef6c87fc2e700;Parent=9a9197af755a6419;Sampled=1';
15+
16+
private $impl, $length, $event;
17+
18+
/**
19+
* Creates a new `run` subcommand
20+
*
21+
* @param string $handler
22+
* @param ?string $event
23+
* @throws lang.ClassLoadingException
24+
*/
25+
public function __construct($handler, $event= null) {
26+
$this->impl= XPClass::forName($handler);
27+
if (null === $event) {
28+
$this->length= 0;
29+
$this->event= null;
30+
} else {
31+
$this->length= strlen($event);
32+
$this->event= json_decode($event, true);
33+
}
34+
}
35+
36+
/** Runs this command */
37+
public function run(): int {
38+
$name= $this->impl->getSimpleName();
39+
$region= getenv('AWS_REGION') ?: 'test-local-1';
40+
$context= new Context(
41+
[
42+
'Lambda-Runtime-Aws-Request-Id' => [UUID::randomUUID()->hashCode()],
43+
'Lambda-Runtime-Invoked-Function-Arn' => ["arn:aws:lambda:{$region}:123456789012:function:{$name}"],
44+
'Lambda-Runtime-Trace-Id' => [self::TRACE_ID],
45+
'Lambda-Runtime-Deadline-Ms' => [(time() + 900) * 1000],
46+
'Content-Length' => [$this->length],
47+
],
48+
$_ENV + ['AWS_LAMBDA_FUNCTION_NAME' => $name, 'AWS_REGION' => $region]
49+
);
50+
51+
try {
52+
$lambda= $this->impl->newInstance(new Environment(getcwd(), Console::$out, []))->target();
53+
$result= $lambda instanceof Lambda ? $lambda->process($this->event, $context) : $lambda($this->event, $context);
54+
Console::$out->writeLine($result);
55+
return 0;
56+
} catch (Throwable $e) {
57+
Console::$err->writeLine($e);
58+
return 1;
59+
}
60+
}
61+
}

src/main/php/xp/lambda/Runner.class.php

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,35 +8,39 @@
88
* XP AWS Lambda
99
* =============
1010
*
11-
* - Store runtime layer as `runtime-X.X.X.zip`, building if necessary:
11+
* - Run lambda locally:
1212
* ```sh
13-
* $ xp lambda runtime
13+
* $ xp lambda run Greet '{"name":"Test"}'
1414
* ```
15-
* - Rebuild runtime:
15+
* - Package single file in `function.zip` file for deployment:
1616
* ```sh
17-
* $ xp lambda runtime -b
17+
* $ xp lambda package Greet.class.php
1818
* ```
19-
* - Speficy runtime version, selecting newest PHP 8.0 release:
19+
* - Package INI file and source directory in `function.zip`:
2020
* ```sh
21-
* $ xp lambda runtime:8.0
21+
* $ xp lambda package task.ini src/main/php
2222
* ```
23-
* - Test lambda:
23+
* - Test lambda inside a containerized AWS environment:
2424
* ```sh
2525
* $ xp lambda test Greet '{"name":"Test"}'
2626
* ```
2727
* - Test lambda, pass environment variables:
2828
* ```sh
2929
* $ xp lambda test -e PROFILE=prod Audit
3030
* ```
31-
* - Package single file in `function.zip` file for deployment:
31+
* - Store runtime layer as `runtime-X.X.X.zip`, building if necessary:
3232
* ```sh
33-
* $ xp lambda package Greet.class.php
33+
* $ xp lambda runtime
3434
* ```
35-
* - Package INI file and source directory in `function.zip`:
35+
* - Rebuild runtime:
3636
* ```sh
37-
* $ xp lambda package task.ini src/main/php
37+
* $ xp lambda runtime -b
38+
* ```
39+
* - Speficy runtime version, selecting newest PHP 8.0 release:
40+
* ```sh
41+
* $ xp lambda runtime:8.0
3842
* ```
39-
* The `runtime` and `test` commands require Docker or Podman to be installed!
43+
* The `test` and `runtime` commands require Docker or Podman to be installed!
4044
* Packaging will always include the `vendor` directory automatically.
4145
*/
4246
class Runner {
@@ -66,6 +70,7 @@ private static function command(string $name, array $args): object {
6670
sscanf($name, "%[^:]:%[^\r]", $command, $version);
6771
switch ($command) {
6872
case 'package': return new PackageLambda(new Path('function.zip'), new Sources(new Path('.'), [...$args, 'vendor']));
73+
case 'run': return new RunLambda($args[0], $args[1] ?? null);
6974
case 'runtime': return new CreateRuntime(self::resolve($version), new Path('runtime-%s.zip'), in_array('-b', $args));
7075
case 'test': return new TestLambda(self::resolve($version), new Path('.'), $args);
7176
default: return new DisplayError('Unknown command "'.$args[0].'"');

0 commit comments

Comments
 (0)