Merge pull request #2807 from appwrite/feat-executor-improvements

feat: retry execution logic
This commit is contained in:
Eldad A. Fux
2022-02-21 16:05:13 +02:00
committed by GitHub
26 changed files with 439 additions and 712 deletions
+1
View File
@@ -2,6 +2,7 @@
/vendor/
/node_modules/
/tests/resources/storage/
/tests/resources/functions/**/code.tar.gz
/app/sdks/*
/.idea/
.DS_Store
+4 -2
View File
@@ -519,7 +519,9 @@ App::post('/v1/functions/:functionId/deployments')
throw new Exception('Failed moving file', 500);
}
if ((bool) $activate) {
$activate = (bool) filter_var($activate, FILTER_VALIDATE_BOOLEAN);
if ($activate) {
// Remove deploy for all other deployments.
$deployments = $dbForProject->find('deployments', [
new Query('activate', Query::TYPE_EQUAL, [true]),
@@ -545,7 +547,7 @@ App::post('/v1/functions/:functionId/deployments')
'path' => $path,
'size' => $size,
'search' => implode(' ', [$deploymentId, $entrypoint]),
'activate' => ((bool) $activate === true),
'activate' => $activate,
]));
// Enqueue a message to start the build
+1 -1
View File
@@ -598,7 +598,7 @@ App::post('/v1/projects/:projectId/webhooks')
throw new Exception('Project not found', 404);
}
$security = ($security === '1' || $security === 'true' || $security === 1 || $security === true);
$security = (bool) filter_var($security, FILTER_VALIDATE_BOOLEAN);
$webhook = new Document([
'$id' => $dbForConsole->getId(),
+142 -200
View File
@@ -12,6 +12,7 @@ use Swoole\Timer;
use Utopia\App;
use Utopia\CLI\Console;
use Utopia\Logger\Log;
use Utopia\Logger\Logger;
use Utopia\Orchestration\Adapter\DockerCLI;
use Utopia\Orchestration\Orchestration;
use Utopia\Storage\Device\Local;
@@ -20,29 +21,10 @@ use Utopia\Swoole\Request;
use Utopia\Swoole\Response;
use Utopia\Validator\ArrayList;
use Utopia\Validator\Assoc;
use Utopia\Validator\Boolean;
use Utopia\Validator\Range as ValidatorRange;
use Utopia\Validator\Text;
// TODO
// Implement other endpoints - Done
// Handle shutdown - Done
// Get list of supported runtimes on startup - Done
// Pull runtimes on startup -- Done
// Move some logic to server start - Done
// Add updated property to swoole table - Done
// Clean up deployments older than X seconds - Done
// Remove orphans on startup - done
// Remove multiple request attempt to the runtime logic in executor - done
// Remove builds param from delete endpoint - done
// Shutdown callback isn't working as expected - done
// Fix error handling - done
// Decide on logic for build and runtime containers names ( runtime-ID and build-ID) - done
// Add size validators for the runtime IDs - done
// Fix logging
// Fix delete endpoint
// Incorporate Matej's changes in the build stage ( moving of the tar file will be performed by the runtime and not the build stage )
Runtime::enableCoroutine(true, SWOOLE_HOOK_ALL);
@@ -71,11 +53,23 @@ $orchestrationPool = new ConnectionPool(function () {
return $orchestration;
}, 10);
/**
* Create logger instance
*/
$providerName = App::getEnv('_APP_LOGGING_PROVIDER', '');
$providerConfig = App::getEnv('_APP_LOGGING_CONFIG', '');
$logger = null;
if(!empty($providerName) && !empty($providerConfig) && Logger::hasProvider($providerName)) {
$classname = '\\Utopia\\Logger\\Adapter\\'.\ucfirst($providerName);
$adapter = new $classname($providerConfig);
$logger = new Logger($adapter);
}
function logError(Throwable $error, string $action, Utopia\Route $route = null)
{
global $register;
$logger = $register->get('logger');
global $logger;
if ($logger) {
$version = App::getEnv('_APP_VERSION', 'UNKNOWN');
@@ -116,55 +110,56 @@ function logError(Throwable $error, string $action, Utopia\Route $route = null)
App::post('/v1/runtimes')
->desc("Create a new runtime server")
->param('runtimeId', '', new Text(62), 'Unique runtime ID.')
->param('runtimeId', '', new Text(64), 'Unique runtime ID.')
->param('source', '', new Text(0), 'Path to source files.')
->param('destination', '', new Text(0), 'Destination folder to store build files into.')
->param('destination', '', new Text(0), 'Destination folder to store build files into.', true)
->param('vars', [], new Assoc(), 'Environment Variables required for the build')
->param('commands', [], new ArrayList(new Text(0)), 'Commands required to build the container')
->param('runtime', '', new Text(128), 'Runtime for the cloud function')
->param('network', '', new Text(128), 'Network to attach the container to')
->param('baseImage', '', new Text(128), 'Base image name of the runtime')
->param('entrypoint', '', new Text(256), 'Entrypoint of the code file', true)
->param('remove', false, new Boolean(), 'Remove a runtime after execution')
->param('workdir', '', new Text(256), 'Working directory', true)
->inject('orchestrationPool')
->inject('activeRuntimes')
->inject('response')
->action(function (string $runtimeId, string $source, string $destination, array $vars, array $commands, string $runtime, string $baseImage, $orchestrationPool, $activeRuntimes, Response $response) {
->action(function (string $runtimeId, string $source, string $destination, array $vars, array $commands, string $runtime, string $network, string $baseImage, string $entrypoint, bool $remove, string $workdir, $orchestrationPool, $activeRuntimes, Response $response) {
$container = 'r-' . $runtimeId;
if ($activeRuntimes->exists($container)) {
if ($activeRuntimes->exists($runtimeId)) {
throw new Exception('Runtime already exists.', 409);
}
$build = [];
$buildId = '';
$buildStdout = '';
$buildStderr = '';
$buildStart = \time();
$buildEnd = 0;
$container = [];
$containerId = '';
$stdout = '';
$stderr = '';
$startTime = \time();
$endTime = 0;
try {
Console::info('Building runtime with ID : ' . $runtimeId);
Console::info('Building container : ' . $runtimeId);
/**
* Temporary file paths in the executor
*/
$tmpSource = "/tmp/$runtimeId/code.tar.gz";
$tmpBuildDir = "/tmp/$runtimeId/builds";
$tmpBuild = "/tmp/$runtimeId/builds/code.tar.gz";
/**
* Copy code files from source to a temporary location on the executor
*/
$device = new Local($destination);
$device = new Local();
$buffer = $device->read($source);
if(!$device->write($tmpSource, $buffer)) {
throw new Exception('Failed to copy source code to temporary directory', 500);
};
/**
* Create a temporary folder to store builds
* Create the mount folder
*/
if (!\file_exists($tmpBuildDir)) {
if (!@\mkdir($tmpBuildDir, 0755, true)) {
throw new Exception("Can't create directory : $tmpBuildDir", 500);
if (!\file_exists(\dirname($tmpBuild))) {
if (!@\mkdir(\dirname($tmpBuild), 0755, true)) {
throw new Exception("Failed to create temporary directory", 500);
}
}
@@ -172,174 +167,128 @@ App::post('/v1/runtimes')
* Create container
*/
$orchestration = $orchestrationPool->get();
$container = 'b-' . $runtimeId;
$secret = \bin2hex(\random_bytes(16));
$vars = \array_merge($vars, [
'INTERNAL_RUNTIME_KEY' => $secret,
'INTERNAL_RUNTIME_ENTRYPOINT' => $entrypoint,
]);
$vars = array_map(fn ($v) => strval($v), $vars);
$orchestration
->setCpus(App::getEnv('_APP_FUNCTIONS_CPUS', 1))
->setMemory(App::getEnv('_APP_FUNCTIONS_MEMORY', 256))
->setSwap(App::getEnv('_APP_FUNCTIONS_MEMORY_SWAP', 256));
$buildId = $orchestration->run(
/** Keep the container alive if we have commands to be executed */
$entrypoint = !empty($commands) ? [
'tail',
'-f',
'/dev/null'
] : [];
$containerId = $orchestration->run(
image: $baseImage,
name: $container,
name: $runtimeId,
hostname: $runtimeId,
vars: $vars,
workdir: '/usr/code',
command: $entrypoint,
labels: [
'openruntimes-id' => $runtimeId,
'openruntimes-type' => 'build',
'openruntimes-created' => strval($buildStart),
'openruntimes-type' => 'runtime',
'openruntimes-created' => strval($startTime),
'openruntimes-runtime' => $runtime,
],
command: [
'tail',
'-f',
'/dev/null'
],
hostname: $container,
mountFolder: \dirname($tmpSource),
workdir: $workdir,
volumes: [
"$tmpBuildDir:/usr/builds:rw"
\dirname($tmpSource). ':/tmp:rw',
\dirname($tmpBuild). ":/usr/code:rw"
]
);
if (empty($buildId)) {
if (empty($containerId)) {
throw new Exception('Failed to create build container', 500);
}
/**
* Extract user code into build container
*/
$status = $orchestration->execute(
name: $container,
command: $commands,
stdout: $buildStdout,
stderr: $buildStderr,
timeout: App::getEnv('_APP_FUNCTIONS_TIMEOUT', 900)
);
if (!$status) {
throw new Exception('Failed to build dependenices ' . $buildStderr, 500);
if (!empty($network)) {
$orchestration->networkConnect($runtimeId, $network);
}
// Check if the build was successful by checking if file exists
if (!\file_exists($tmpBuild)) {
throw new Exception('Something went wrong during the build process', 500);
/**
* Execute any commands if they were provided
*/
if (!empty($commands)) {
$status = $orchestration->execute(
name: $runtimeId,
command: $commands,
stdout: $stdout,
stderr: $stderr,
timeout: App::getEnv('_APP_FUNCTIONS_TIMEOUT', 900)
);
if (!$status) {
throw new Exception('Failed to build dependenices ' . $stderr, 500);
}
}
/**
* Move built code to expected build directory
*/
$outputPath = $device->getPath(\uniqid() . '.' . \pathinfo('code.tar.gz', PATHINFO_EXTENSION));
if (!empty($destination)) {
// Check if the build was successful by checking if file exists
if (!\file_exists($tmpBuild)) {
throw new Exception('Something went wrong during the build process', 500);
}
if (App::getEnv('_APP_STORAGE_DEVICE', Storage::DEVICE_LOCAL) === Storage::DEVICE_LOCAL) {
if (!$device->move($tmpBuild, $outputPath)) {
$device = new Local($destination);
$outputPath = $device->getPath(\uniqid() . '.' . \pathinfo('code.tar.gz', PATHINFO_EXTENSION));
$buffer = $device->read($tmpBuild);
if(!$device->write($outputPath, $buffer)) {
throw new Exception('Failed to move built code to storage', 500);
}
} else {
if (!$device->upload($tmpBuild, $outputPath)) {
throw new Exception('Failed to upload built code upload to storage', 500);
}
};
$container['outputPath'] = $outputPath;
}
if ($buildStdout === '') {
$buildStdout = 'Build Successful!';
if (empty($stdout)) {
$stdout = 'Build Successful!';
}
$buildEnd = \time();
$build = [
'outputPath' => $outputPath,
$endTime = \time();
$container = array_merge($container, [
'status' => 'ready',
'stdout' => \utf8_encode($buildStdout),
'stderr' => \utf8_encode($buildStderr),
'startTime' => $buildStart,
'endTime' => $buildEnd,
'duration' => $buildEnd - $buildStart,
];
'stdout' => \utf8_encode($stdout),
'stderr' => \utf8_encode($stderr),
'startTime' => $startTime,
'endTime' => $endTime,
'duration' => $endTime - $startTime,
]);
Console::success('Build Stage completed in ' . ($buildEnd - $buildStart) . ' seconds');
if (!$remove) {
$activeRuntimes->set($runtimeId, [
'id' => $containerId,
'name' => $runtimeId,
'created' => $startTime,
'updated' => $endTime,
'status' => 'Up ' . \round($endTime - $startTime, 2) . 's',
'key' => $secret,
]);
}
Console::success('Build Stage completed in ' . ($endTime - $startTime) . ' seconds');
} catch (Throwable $th) {
Console::error('Build failed: ' . $th->getMessage());
throw new Exception($th->getMessage(), 500);
} finally {
if (!empty($buildId)) {
$orchestration->remove($buildId, true);
if (!empty($containerId) && $remove) {
$orchestration->remove($containerId, true);
}
$orchestrationPool->put($orchestration);
}
/** Create runtime server */
try {
$orchestration = $orchestrationPool->get();
/**
* Copy code files from source to a temporary location on the executor
*/
$buffer = $device->read($outputPath);
if(!$device->write($tmpBuild, $buffer)) {
throw new Exception('Failed to copy built code to temporary location.', 500);
};
/**
* Launch Runtime
*/
$container = 'r-' . $runtimeId;
$secret = \bin2hex(\random_bytes(16));
$vars = \array_merge($vars, [
'INTERNAL_RUNTIME_KEY' => $secret
]);
$executionStart = \microtime(true);
$executionTime = \time();
$vars = array_map(fn ($v) => strval($v), $vars);
$orchestration
->setCpus(App::getEnv('_APP_FUNCTIONS_CPUS', 1))
->setMemory(App::getEnv('_APP_FUNCTIONS_MEMORY', 256))
->setSwap(App::getEnv('_APP_FUNCTIONS_MEMORY_SWAP', 256));
$id = $orchestration->run(
image: $baseImage,
name: $container,
vars: $vars,
labels: [
'openruntimes-id' => $runtimeId,
'openruntimes-type' => 'function',
'openruntimes-created' => strval($executionTime),
'openruntimes-runtime' => $runtime
],
hostname: $container,
mountFolder: \dirname($tmpBuild),
);
if (empty($id)) {
throw new Exception('Failed to create runtime', 500);
}
$orchestration->networkConnect($container, App::getEnv('_APP_EXECUTOR_RUNTIME_NETWORK', 'openruntimes'));
$executionEnd = \microtime(true);
$activeRuntimes->set($container, [
'id' => $id,
'name' => $container,
'created' => $executionTime,
'updated' => $executionTime,
'status' => 'Up ' . \round($executionEnd - $executionStart, 2) . 's',
'key' => $secret,
]);
Console::success('Runtime Server created in ' . ($executionEnd - $executionStart) . ' seconds');
} catch (\Throwable $th) {
Console::error('Runtime Server Creation Failed: '. $th->getMessage());
throw new Exception($th->getMessage(), 500);
} finally {
$orchestrationPool->put($orchestration);
}
$response
->setStatusCode(Response::STATUS_CODE_CREATED)
->json($build);
->json($container);
});
@@ -355,51 +304,47 @@ App::get('/v1/runtimes')
}
$response
->setStatusCode(200)
->setStatusCode(Response::STATUS_CODE_OK)
->json($runtimes);
});
App::get('/v1/runtimes/:runtimeId')
->desc("Get a runtime by its ID")
->param('runtimeId', '', new Text(62), 'Runtime unique ID.')
->param('runtimeId', '', new Text(64), 'Runtime unique ID.')
->inject('activeRuntimes')
->inject('response')
->action(function ($runtimeId, $activeRuntimes, Response $response) {
$container = 'r-' . $runtimeId;
if(!$activeRuntimes->exists($container)) {
if(!$activeRuntimes->exists($runtimeId)) {
throw new Exception('Runtime not found', 404);
}
$runtime = $activeRuntimes->get($container);
$runtime = $activeRuntimes->get($runtimeId);
$response
->setStatusCode(200)
->setStatusCode(Response::STATUS_CODE_OK)
->json($runtime);
});
App::delete('/v1/runtimes/:runtimeId')
->desc('Delete a runtime')
->param('runtimeId', '', new Text(62), 'Runtime unique ID.', false)
->param('runtimeId', '', new Text(64), 'Runtime unique ID.', false)
->inject('orchestrationPool')
->inject('activeRuntimes')
->inject('response')
->action(function (string $runtimeId, $orchestrationPool, $activeRuntimes, Response $response) {
$container = 'r-' . $runtimeId;
if(!$activeRuntimes->exists($container)) {
if(!$activeRuntimes->exists($runtimeId)) {
throw new Exception('Runtime not found', 404);
}
Console::info('Deleting runtime: ' . $container);
Console::info('Deleting runtime: ' . $runtimeId);
try {
$orchestration = $orchestrationPool->get();
$orchestration->remove($container, true);
$activeRuntimes->del($container);
Console::success('Removed runtime container: ' . $container);
$orchestration->remove($runtimeId, true);
$activeRuntimes->del($runtimeId);
Console::success('Removed runtime container: ' . $runtimeId);
} finally {
$orchestrationPool->put($orchestration);
}
@@ -423,7 +368,7 @@ App::delete('/v1/runtimes/:runtimeId')
App::post('/v1/execution')
->desc('Create an execution')
->param('runtimeId', '', new Text(62), 'The runtimeID to execute')
->param('runtimeId', '', new Text(64), 'The runtimeID to execute')
->param('path', '', new Text(0), 'Path containing the built files.', false)
->param('vars', [], new Assoc(), 'Environment variables required for the build', false)
->param('data', '', new Text(8192), 'Data to be forwarded to the function, this is user specified.', true)
@@ -436,13 +381,11 @@ App::post('/v1/execution')
->action(
function (string $runtimeId, string $path, array $vars, string $data, string $runtime, string $entrypoint, $timeout, string $baseImage, $activeRuntimes, Response $response) {
$container = 'r-' . $runtimeId;
if (!$activeRuntimes->exists($container)) {
if (!$activeRuntimes->exists($runtimeId)) {
throw new Exception('Runtime not found. Please create the runtime.', 404);
}
$runtime = $activeRuntimes->get($container);
$runtime = $activeRuntimes->get($runtimeId);
$secret = $runtime['key'];
if (empty($secret)) {
throw new Exception('Runtime secret not found. Please re-create the runtime.', 500);
@@ -460,13 +403,11 @@ App::post('/v1/execution')
$ch = \curl_init();
$body = \json_encode([
'path' => '/usr/code',
'file' => $entrypoint,
'env' => $vars,
'payload' => $data,
'timeout' => $timeout ?? (int) App::getEnv('_APP_FUNCTIONS_TIMEOUT', 900)
]);
\curl_setopt($ch, CURLOPT_URL, "http://" . $container . ":3000/");
\curl_setopt($ch, CURLOPT_URL, "http://" . $runtimeId . ":3000/");
\curl_setopt($ch, CURLOPT_POST, true);
\curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
\curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
@@ -497,7 +438,7 @@ App::post('/v1/execution')
// 110 is the Swoole error code for timeout, see: https://www.swoole.co.uk/docs/swoole-error-code
if ($errNo !== 0 && $errNo !== CURLE_COULDNT_CONNECT && $errNo !== CURLE_OPERATION_TIMEDOUT && $errNo !== 110) {
throw new Exception('An internal curl error has occurred within the executor! Error Msg: ' . $error, 500);
throw new Exception('An internal curl error has occurred within the executor! Error Msg: ' . $error, 406);
}
$executionData = [];
@@ -542,7 +483,7 @@ App::post('/v1/execution')
/** Update swoole table */
$runtime['updated'] = \time();
$activeRuntimes->set($container, $runtime);
$activeRuntimes->set($runtimeId, $runtime);
$response
->setStatusCode(Response::STATUS_CODE_OK)
@@ -559,18 +500,20 @@ App::setResource('orchestrationPool', fn() => $orchestrationPool);
App::setResource('activeRuntimes', fn() => $activeRuntimes);
/** Set callbacks */
App::error(function ($error, $response) {
// $route = $utopia->match($request);
// logError($error, "httpError", $route);
App::error(function ($utopia, $error, $request, $response) {
$route = $utopia->match($request);
logError($error, "httpError", $route);
switch ($error->getCode()) {
case 400: // Error allowed publicly
case 401: // Error allowed publicly
case 402: // Error allowed publicly
case 403: // Error allowed publicly
case 404: // Error allowed publicly
case 406: // Error allowed publicly
case 409: // Error allowed publicly
case 412: // Error allowed publicly
case 425: // Error allowed publicly
case 429: // Error allowed publicly
case 501: // Error allowed publicly
case 503: // Error allowed publicly
@@ -586,7 +529,7 @@ App::error(function ($error, $response) {
'file' => $error->getFile(),
'line' => $error->getLine(),
'trace' => $error->getTrace(),
'version' => App::getEnv('OPENRUNTIMES_VERSION', 'UNKNOWN'),
'version' => App::getEnv('_APP_VERSION', 'UNKNOWN')
];
$response
@@ -596,7 +539,7 @@ App::error(function ($error, $response) {
->setStatusCode($code);
$response->json($output);
}, ['error', 'response']);
}, ['utopia', 'error', 'request', 'response']);
App::init(function ($request, $response) {
$secretKey = $request->getHeader('x-appwrite-executor-key', '');
@@ -644,8 +587,7 @@ $http->on('start', function ($http) {
Console::info('Removing orphan runtimes...');
try {
$orchestration = $orchestrationPool->get();
$orphans = $orchestration->list(['label' => 'openruntimes-type=function']);
} catch (\Throwable $th) {
$orphans = $orchestration->list(['label' => 'openruntimes-type=runtime']);
} finally {
$orchestrationPool->put($orchestration);
}
@@ -715,7 +657,7 @@ $http->on('beforeShutdown', function() {
Console::info('Cleaning up containers before shutdown...');
$orchestration = $orchestrationPool->get();
$functionsToRemove = $orchestration->list(['label' => 'openruntimes-type=function']);
$functionsToRemove = $orchestration->list(['label' => 'openruntimes-type=runtime']);
$orchestrationPool->put($orchestration);
foreach ($functionsToRemove as $container) {
@@ -742,7 +684,7 @@ $http->on('request', function (SwooleRequest $swooleRequest, SwooleResponse $swo
try {
$app->run($request, $response);
} catch (\Throwable $th) {
// logError($e, "serverError");
logError($th, "serverError");
$swooleResponse->setStatusCode(500);
$output = [
'message' => 'Error: '. $th->getMessage(),
+1 -1
View File
@@ -687,7 +687,7 @@ $usageStatsEnabled = $this->getParam('usageStatsEnabled', true);
<input type="file" name="code" id="deployment-code" size="1" required accept="application/x-gzip,.gz">
<div class="text-fade text-size-xs margin-top-negative-small margin-bottom">(Max file size allowed: <?php echo $fileLimitHuman; ?>)</div>
<label for="deployment-activate" class="margin-bottom-large">Auto Activate Deployment after build <input type="checkbox" class="margin-start-small" id="deployment-activate" name="activate" /></label>
<label for="deployment-activate" class="margin-bottom-large"><input type="checkbox" class="margin-start-small" id="deployment-activate" name="activate" /> Activate Deployment after build</label>
<footer>
<button type="submit">Create</button> &nbsp; <button data-ui-modal-close="" type="button" class="reverse">Cancel</button>
+5 -8
View File
@@ -117,19 +117,16 @@ class BuildsV1 extends Worker
functionId: $functionId,
deploymentId: $deploymentId,
source: $source,
destination: APP_STORAGE_BUILDS . "/app-$projectId",
vars: $vars,
runtime: $key,
baseImage: $baseImage,
workdir: '/usr/code',
remove: true,
commands: [
'sh', '-c',
'mkdir -p /usr/code && \
cp /tmp/code.tar.gz /usr/workspace/code.tar.gz && \
cd /usr/workspace/ && \
tar -zxf /usr/workspace/code.tar.gz -C /usr/code && \
rm /usr/workspace/code.tar.gz && \
cd /usr/local/src && \
./build.sh && \
tar -C /usr/code -czf /usr/builds/code.tar.gz ./'
'tar -zxf /tmp/code.tar.gz -C /usr/code && \
cd /usr/local/src/ && ./build.sh'
]
);
+1 -1
View File
@@ -42,7 +42,7 @@
"ext-zlib": "*",
"ext-sockets": "*",
"appwrite/php-clamav": "1.1.*",
"appwrite/php-runtimes": "dev-refactor",
"appwrite/php-runtimes": "0.7.2",
"utopia-php/framework": "0.19.*",
"utopia-php/logger": "0.1.*",
"utopia-php/abuse": "0.7.*",
Generated
+17 -25
View File
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "70ce232aec13929c9cc7901fa34282a0",
"content-hash": "366fe0389feaf13e3b3132b684ea2e20",
"packages": [
{
"name": "adhocore/jwt",
@@ -115,20 +115,18 @@
},
{
"name": "appwrite/php-runtimes",
"version": "dev-refactor",
"version": "0.7.0",
"source": {
"type": "git",
"url": "https://github.com/appwrite/runtimes.git",
"reference": "ea44eb19af851a3fe4ecf73e789f374f70d778c5"
"reference": "e41ecbfec8c4adb1f5da01dc70c2578a7e32e9c6"
},
"require": {
"php": ">=8.0",
"utopia-php/orchestration": "0.4.*",
"utopia-php/system": "0.4.*"
},
"require-dev": {
"phpunit/phpunit": "^9.3",
"utopia-php/cli": "0.11.*",
"vimeo/psalm": "4.0.1"
},
"type": "library",
@@ -148,10 +146,6 @@
{
"name": "Torsten Dittmann",
"email": "torsten@appwrite.io"
},
{
"name": "Bradley Schofield",
"email": "bradley@appwrite.io"
}
],
"description": "Appwrite repository for Cloud Function runtimes that contains the configurations and tests for all of the Appwrite runtime environments.",
@@ -160,7 +154,7 @@
"php",
"runtimes"
],
"time": "2022-02-17T12:06:12+00:00"
"time": "2022-02-19T00:08:41+00:00"
},
{
"name": "chillerlan/php-qrcode",
@@ -2252,16 +2246,16 @@
},
{
"name": "utopia-php/framework",
"version": "0.19.6",
"version": "0.19.7",
"source": {
"type": "git",
"url": "https://github.com/utopia-php/framework.git",
"reference": "7d9b28365fb794001cb34dd028659452d4e71b7d"
"reference": "f17afe77a21873b9be18ebc05283813468b4283a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/utopia-php/framework/zipball/7d9b28365fb794001cb34dd028659452d4e71b7d",
"reference": "7d9b28365fb794001cb34dd028659452d4e71b7d",
"url": "https://api.github.com/repos/utopia-php/framework/zipball/f17afe77a21873b9be18ebc05283813468b4283a",
"reference": "f17afe77a21873b9be18ebc05283813468b4283a",
"shasum": ""
},
"require": {
@@ -2295,9 +2289,9 @@
],
"support": {
"issues": "https://github.com/utopia-php/framework/issues",
"source": "https://github.com/utopia-php/framework/tree/0.19.6"
"source": "https://github.com/utopia-php/framework/tree/0.19.7"
},
"time": "2022-02-10T17:05:22+00:00"
"time": "2022-02-18T00:04:49+00:00"
},
{
"name": "utopia-php/image",
@@ -4235,16 +4229,16 @@
},
{
"name": "phpunit/php-code-coverage",
"version": "9.2.10",
"version": "9.2.11",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
"reference": "d5850aaf931743067f4bfc1ae4cbd06468400687"
"reference": "665a1ac0a763c51afc30d6d130dac0813092b17f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/d5850aaf931743067f4bfc1ae4cbd06468400687",
"reference": "d5850aaf931743067f4bfc1ae4cbd06468400687",
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/665a1ac0a763c51afc30d6d130dac0813092b17f",
"reference": "665a1ac0a763c51afc30d6d130dac0813092b17f",
"shasum": ""
},
"require": {
@@ -4300,7 +4294,7 @@
],
"support": {
"issues": "https://github.com/sebastianbergmann/php-code-coverage/issues",
"source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.10"
"source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.11"
},
"funding": [
{
@@ -4308,7 +4302,7 @@
"type": "github"
}
],
"time": "2021-12-05T09:12:13+00:00"
"time": "2022-02-18T12:46:09+00:00"
},
{
"name": "phpunit/php-file-iterator",
@@ -6638,9 +6632,7 @@
],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": {
"appwrite/php-runtimes": 20
},
"stability-flags": [],
"prefer-stable": false,
"prefer-lowest": false,
"platform": {
-4
View File
@@ -497,10 +497,6 @@ services:
- _APP_INFLUXDB_HOST
- _APP_INFLUXDB_PORT
- _APP_USAGE_SYNC_INTERVAL
- _APP_REDIS_HOST
- _APP_REDIS_PORT
- _APP_REDIS_USER
- _APP_REDIS_PASS
appwrite-schedule:
entrypoint: schedule
+56 -18
View File
@@ -4,6 +4,7 @@ namespace Executor;
use Exception;
use Utopia\App;
use Utopia\CLI\Console;
class Executor
{
@@ -34,29 +35,37 @@ class Executor
string $functionId,
string $deploymentId,
string $projectId,
string $source,
array $vars,
string $source,
string $runtime,
string $baseImage,
array $commands
bool $remove = false,
string $entrypoint = '',
string $workdir = '',
string $destination = '',
string $network = '',
array $vars = [],
array $commands = []
) {
$route = "/runtimes";
$headers = [
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
'x-appwrite-executor-key' => App::getEnv('_APP_EXECUTOR_SECRET', '')
];
$params = [
'runtimeId' => "$projectId-$deploymentId",
'source' => $source,
'destination' => APP_STORAGE_BUILDS . "/app-$projectId",
'vars' => $vars,
'destination' => $destination,
'runtime' => $runtime,
'baseImage' => $baseImage,
'entrypoint' => $entrypoint,
'workdir' => $workdir,
'network' => empty($network) ? App::getEnv('_APP_EXECUTOR_RUNTIME_NETWORK', 'appwrite_runtimes') : $network,
'vars' => $vars,
'remove' => $remove,
'commands' => $commands
];
$response = $this->call(self::METHOD_POST, $route, $headers, $params, true, 30);
$response = $this->call(self::METHOD_POST, $route, $headers, $params, true, App::getEnv('_APP_FUNCTIONS_TIMEOUT', 900));
$status = $response['headers']['status-code'];
if ($status >= 400) {
@@ -72,7 +81,6 @@ class Executor
$route = "/runtimes/$runtimeId";
$headers = [
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
'x-appwrite-executor-key' => App::getEnv('_APP_EXECUTOR_SECRET', '')
];
@@ -99,12 +107,11 @@ class Executor
string $runtime,
string $baseImage,
$timeout
)
{
) {
$route = "/execution";
$headers = [
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
'x-appwrite-executor-key' => App::getEnv('_APP_EXECUTOR_SECRET', '')
];
$params = [
@@ -119,11 +126,46 @@ class Executor
];
$response = $this->call(self::METHOD_POST, $route, $headers, $params, true, 30);
$status = $response['headers']['status-code'];
if ($status >= 400) {
throw new \Exception($response['body']['message'], $status);
}
for ($attempts = 0; $attempts < 5; $attempts++) {
switch ($status) {
case 404:
$response = $this->createRuntime(
functionId: $functionId,
deploymentId: $deploymentId,
projectId: $projectId,
source: $path,
runtime: $runtime,
baseImage: $baseImage,
vars: $vars,
entrypoint: $entrypoint,
commands: []
);
$response = $this->call(self::METHOD_POST, $route, $headers, $params, true, 30);
$status = $response['headers']['status-code'];
break;
case 406:
$response = $this->call(self::METHOD_POST, $route, $headers, $params, true, 30);
$status = $response['headers']['status-code'];
break;
default:
throw new \Exception($response['body']['message'], $status);
}
if ($status < 400) {
return $response['body'];
}
if ($status != 406) {
throw new \Exception($response['body']['message'], $status);
}
sleep(2);
}
throw new Exception($response['body']['message'], 503);
}
return $response['body'];
}
@@ -225,10 +267,6 @@ class Executor
$responseHeaders['status-code'] = $responseStatus;
if ($responseStatus === 500) {
echo 'Server error('.$method.': '.$path.'. Params: '.json_encode($params).'): '.json_encode($responseBody)."\n";
}
return [
'headers' => $responseHeaders,
'body' => $responseBody
@@ -3,10 +3,16 @@
namespace Tests\E2E\Services\Functions;
use Tests\E2E\Client;
use Utopia\CLI\Console;
trait FunctionsBase
{
protected string $stdout = '';
protected string $stderr = '';
protected function packageCode($folder) {
Console::execute('cd '.realpath(__DIR__ . "/../../../resources/functions") . "/$folder && tar --exclude code.tar.gz -czf code.tar.gz .", '', $this->stdout, $this->stderr);
}
// /**
// * @depends testCreateTeam
@@ -7,6 +7,7 @@ use Tests\E2E\Client;
use Tests\E2E\Scopes\ProjectCustom;
use Tests\E2E\Scopes\Scope;
use Tests\E2E\Scopes\SideClient;
use Utopia\CLI\Console;
use Utopia\Database\Database;
class FunctionsCustomClientTest extends Scope
@@ -73,13 +74,17 @@ class FunctionsCustomClientTest extends Scope
$this->assertEquals(201, $function['headers']['status-code']);
$folder = 'php';
$code = realpath(__DIR__ . '/../../../resources/functions'). "/$folder/code.tar.gz";
$this->packageCode($folder);
$deployment = $this->client->call(Client::METHOD_POST, '/functions/'.$function['body']['$id'].'/deployments', [
'content-type' => 'multipart/form-data',
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey'],
], [
'entrypoint' => 'index.php',
'code' => new CURLFile(realpath(__DIR__ . '/../../../resources/functions/php.tar.gz'), 'application/x-gzip', 'php-fx.tar.gz'),
'code' => new CURLFile($code, 'application/x-gzip', \basename($code)),
]);
$deploymentId = $deployment['body']['$id'] ?? '';
@@ -156,13 +161,17 @@ class FunctionsCustomClientTest extends Scope
$this->assertEquals(201, $function['headers']['status-code']);
$folder = 'php-fn';
$code = realpath(__DIR__ . '/../../../resources/functions'). "/$folder/code.tar.gz";
$this->packageCode($folder);
$deployment = $this->client->call(Client::METHOD_POST, '/functions/'.$functionId.'/deployments', [
'content-type' => 'multipart/form-data',
'x-appwrite-project' => $projectId,
'x-appwrite-key' => $apikey,
], [
'entrypoint' => 'index.php',
'code' => new CURLFile(realpath(__DIR__ . '/../../../resources/functions/php-fn.tar.gz'), 'application/x-gzip', 'php-fx.tar.gz'), //different tarball names intentional
'code' => new CURLFile($code, 'application/x-gzip', \basename($code)), //different tarball names intentional
]);
$deploymentId = $deployment['body']['$id'] ?? '';
@@ -338,13 +347,17 @@ class FunctionsCustomClientTest extends Scope
$this->assertEquals(201, $function['headers']['status-code']);
$folder = 'php-fn';
$code = realpath(__DIR__ . '/../../../resources/functions'). "/$folder/code.tar.gz";
$this->packageCode($folder);
$deployment = $this->client->call(Client::METHOD_POST, '/functions/'.$functionId.'/deployments', [
'content-type' => 'multipart/form-data',
'x-appwrite-project' => $projectId,
'x-appwrite-key' => $apikey,
], [
'entrypoint' => 'index.php',
'code' => new CURLFile(realpath(__DIR__ . '/../../../resources/functions/php-fn.tar.gz'), 'application/x-gzip', 'php-fx.tar.gz'), //different tarball names intentional
'code' => new CURLFile($code, 'application/x-gzip', \basename($code)), //different tarball names intentional
]);
$deploymentId = $deployment['body']['$id'] ?? '';
@@ -7,6 +7,7 @@ use Tests\E2E\Client;
use Tests\E2E\Scopes\ProjectCustom;
use Tests\E2E\Scopes\Scope;
use Tests\E2E\Scopes\SideServer;
use Utopia\CLI\Console;
use Utopia\Database\Database;
class FunctionsCustomServerTest extends Scope
@@ -281,12 +282,16 @@ class FunctionsCustomServerTest extends Scope
/**
* Test for SUCCESS
*/
$folder = 'php';
$code = realpath(__DIR__ . '/../../../resources/functions'). "/$folder/code.tar.gz";
$this->packageCode($folder);
$deployment = $this->client->call(Client::METHOD_POST, '/functions/'.$data['functionId'].'/deployments', array_merge([
'content-type' => 'multipart/form-data',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'entrypoint' => 'index.php',
'code' => new CURLFile(realpath(__DIR__ . '/../../../resources/functions/php.tar.gz'), 'application/x-gzip', 'php-fx.tar.gz'),
'code' => new CURLFile($code, 'application/x-gzip', \basename($code)),
]);
$deploymentId = $deployment['body']['$id'] ?? '';
@@ -654,10 +659,12 @@ class FunctionsCustomServerTest extends Scope
public function testTimeout()
{
$name = 'php-8.0';
$code = realpath(__DIR__ . '/../../../resources/functions').'/timeout.tar.gz';
$entrypoint = 'index.php';
$timeout = 2;
$folder = 'timeout';
$code = realpath(__DIR__ . '/../../../resources/functions'). "/$folder/code.tar.gz";
$this->packageCode($folder);
$function = $this->client->call(Client::METHOD_POST, '/functions', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
@@ -681,20 +688,13 @@ class FunctionsCustomServerTest extends Scope
], $this->getHeaders()), [
'entrypoint' => $entrypoint,
'code' => new CURLFile($code, 'application/x-gzip', basename($code)),
'activate' => true,
]);
$deploymentId = $deployment['body']['$id'] ?? '';
$this->assertEquals(201, $deployment['headers']['status-code']);
// Allow build step to run
sleep(10);
$deployment = $this->client->call(Client::METHOD_PATCH, '/functions/'.$functionId.'/deployments/'.$deploymentId, array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), []);
$this->assertEquals(200, $deployment['headers']['status-code']);
sleep(5);
$execution = $this->client->call(Client::METHOD_POST, '/functions/'.$functionId.'/executions', array_merge([
'content-type' => 'application/json',
@@ -707,7 +707,7 @@ class FunctionsCustomServerTest extends Scope
$this->assertEquals(201, $execution['headers']['status-code']);
sleep(10);
sleep(5);
$executions = $this->client->call(Client::METHOD_GET, '/functions/'.$functionId.'/executions', array_merge([
'content-type' => 'application/json',
@@ -740,12 +740,14 @@ class FunctionsCustomServerTest extends Scope
/**
* @depends testTimeout
*/
public function testCreateCustomExecution()
public function testCreateCustomPHPExecution()
{
$name = 'php-8.0';
$code = realpath(__DIR__ . '/../../../resources/functions').'/php-fn.tar.gz';
$entrypoint = 'index.php';
$timeout = 2;
$folder = 'php-fn';
$code = realpath(__DIR__ . '/../../../resources/functions'). "/$folder/code.tar.gz";
$this->packageCode($folder);
$function = $this->client->call(Client::METHOD_POST, '/functions', array_merge([
'content-type' => 'application/json',
@@ -845,9 +847,114 @@ class FunctionsCustomServerTest extends Scope
$this->assertEquals(204, $response['headers']['status-code']);
}
public function testCreateCustomNodeExecution()
{
$name = 'node-17.0';
$folder = 'node';
$code = realpath(__DIR__ . '/../../../resources/functions'). "/$folder/code.tar.gz";
$this->packageCode($folder);
$entrypoint = 'index.js';
$timeout = 2;
$function = $this->client->call(Client::METHOD_POST, '/functions', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'functionId' => 'unique()',
'name' => 'Test '.$name,
'runtime' => $name,
'vars' => [
'CUSTOM_VARIABLE' => 'variable',
],
'events' => [],
'schedule' => '',
'timeout' => $timeout,
]);
$functionId = $function['body']['$id'] ?? '';
$this->assertEquals(201, $function['headers']['status-code']);
$deployment = $this->client->call(Client::METHOD_POST, '/functions/'.$functionId.'/deployments', array_merge([
'content-type' => 'multipart/form-data',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'entrypoint' => $entrypoint,
'code' => new CURLFile($code, 'application/x-gzip', basename($code)),
'activate' => true,
]);
$deploymentId = $deployment['body']['$id'] ?? '';
$this->assertEquals(201, $deployment['headers']['status-code']);
// Allow build step to run
sleep(10);
$execution = $this->client->call(Client::METHOD_POST, '/functions/'.$functionId.'/executions', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'data' => 'foobar',
]);
$executionId = $execution['body']['$id'] ?? '';
$this->assertEquals(201, $execution['headers']['status-code']);
$executionId = $execution['body']['$id'] ?? '';
sleep(10);
$executions = $this->client->call(Client::METHOD_GET, '/functions/'.$functionId.'/executions/'.$executionId, array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()));
$output = json_decode($executions['body']['stdout'], true);
$this->assertEquals(200, $executions['headers']['status-code']);
$this->assertEquals('completed', $executions['body']['status']);
$this->assertEquals($functionId, $output['APPWRITE_FUNCTION_ID']);
$this->assertEquals('Test '.$name, $output['APPWRITE_FUNCTION_NAME']);
$this->assertEquals($deploymentId, $output['APPWRITE_FUNCTION_DEPLOYMENT']);
$this->assertEquals('http', $output['APPWRITE_FUNCTION_TRIGGER']);
$this->assertEquals('Node.js', $output['APPWRITE_FUNCTION_RUNTIME_NAME']);
$this->assertEquals('17.0', $output['APPWRITE_FUNCTION_RUNTIME_VERSION']);
$this->assertEquals('', $output['APPWRITE_FUNCTION_EVENT']);
$this->assertEquals('', $output['APPWRITE_FUNCTION_EVENT_DATA']);
$this->assertEquals('foobar', $output['APPWRITE_FUNCTION_DATA']);
$this->assertEquals('variable', $output['CUSTOM_VARIABLE']);
$this->assertEquals('', $output['APPWRITE_FUNCTION_USER_ID']);
$this->assertEmpty($output['APPWRITE_FUNCTION_JWT']);
$this->assertEquals($this->getProject()['$id'], $output['APPWRITE_FUNCTION_PROJECT_ID']);
$executions = $this->client->call(Client::METHOD_GET, '/functions/'.$functionId.'/executions', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()));
$this->assertEquals($executions['headers']['status-code'], 200);
$this->assertEquals($executions['body']['sum'], 1);
$this->assertIsArray($executions['body']['executions']);
$this->assertCount(1, $executions['body']['executions']);
$this->assertEquals($executions['body']['executions'][0]['$id'], $executionId);
$this->assertEquals($executions['body']['executions'][0]['trigger'], 'http');
$this->assertStringContainsString('foobar', $executions['body']['executions'][0]['stdout']);
// Cleanup : Delete function
$response = $this->client->call(Client::METHOD_DELETE, '/functions/'. $functionId, [
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey'],
], []);
$this->assertEquals(204, $response['headers']['status-code']);
}
public function testGetRuntimes()
{
$runtimes = $this->client->call(Client::METHOD_GET, '/functions/runtimes', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
@@ -7,6 +7,7 @@ use Tests\E2E\Client;
use Tests\E2E\Scopes\Scope;
use Tests\E2E\Scopes\ProjectCustom;
use Tests\E2E\Scopes\SideClient;
use Utopia\CLI\Console;
use WebSocket\ConnectionException;
@@ -985,13 +986,19 @@ class RealtimeCustomClientTest extends Scope
$this->assertEquals($function['headers']['status-code'], 201);
$this->assertNotEmpty($function['body']['$id']);
$folder = 'timeout';
$stderr = '';
$stdout= '';
$code = realpath(__DIR__ . '/../../../resources/functions'). "/$folder/code.tar.gz";
Console::execute('cd '.realpath(__DIR__ . "/../../../resources/functions") . "/$folder && tar --exclude code.tar.gz -czf code.tar.gz .", '', $stdout, $stderr);
$deployment = $this->client->call(Client::METHOD_POST, '/functions/'.$functionId.'/deployments', array_merge([
'content-type' => 'multipart/form-data',
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey']
]), [
'entrypoint' => 'index.php',
'code' => new CURLFile(realpath(__DIR__ . '/../../../resources/functions/timeout.tar.gz'), 'application/x-gzip', 'php-fx.tar.gz'),
'code' => new CURLFile($code, 'application/x-gzip', basename($code))
]);
$deploymentId = $deployment['body']['$id'] ?? '';
@@ -7,6 +7,7 @@ use Tests\E2E\Client;
use Tests\E2E\Scopes\ProjectCustom;
use Tests\E2E\Scopes\Scope;
use Tests\E2E\Scopes\SideServer;
use Utopia\CLI\Console;
class WebhooksCustomServerTest extends Scope
{
@@ -398,12 +399,18 @@ class WebhooksCustomServerTest extends Scope
/**
* Test for SUCCESS
*/
$stderr = '';
$stdout= '';
$folder = 'timeout';
$code = realpath(__DIR__ . '/../../../resources/functions'). "/$folder/code.tar.gz";
Console::execute('cd '.realpath(__DIR__ . "/../../../resources/functions") . "/$folder && tar --exclude code.tar.gz -czf code.tar.gz .", '', $stdout, $stderr);
$deployment = $this->client->call(Client::METHOD_POST, '/functions/'.$data['functionId'].'/deployments', array_merge([
'content-type' => 'multipart/form-data',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'entrypoint' => 'index.php',
'code' => new CURLFile(realpath(__DIR__ . '/../../../resources/functions/timeout.tar.gz'), 'application/x-gzip', 'php-fx.tar.gz'),
'code' => new CURLFile($code, 'application/x-gzip', \basename($code))
]);
$deploymentId = $deployment['body']['$id'] ?? '';
+29
View File
@@ -0,0 +1,29 @@
/*
'req' variable has:
'headers' - object with request headers
'payload' - object with request body data
'env' - object with environment variables
'res' variable has:
'send(text, status)' - function to return text response. Status code defaults to 200
'json(obj, status)' - function to return JSON response. Status code defaults to 200
If an error is thrown, a response with code 500 will be returned.
*/
module.exports = async (req, res) => {
res.json({
'APPWRITE_FUNCTION_ID' : req.env.APPWRITE_FUNCTION_ID,
'APPWRITE_FUNCTION_NAME' : req.env.APPWRITE_FUNCTION_NAME,
'APPWRITE_FUNCTION_DEPLOYMENT' : req.env.APPWRITE_FUNCTION_DEPLOYMENT,
'APPWRITE_FUNCTION_TRIGGER' : req.env.APPWRITE_FUNCTION_TRIGGER,
'APPWRITE_FUNCTION_RUNTIME_NAME' : req.env.APPWRITE_FUNCTION_RUNTIME_NAME,
'APPWRITE_FUNCTION_RUNTIME_VERSION' : req.env.APPWRITE_FUNCTION_RUNTIME_VERSION,
'APPWRITE_FUNCTION_EVENT' : req.env.APPWRITE_FUNCTION_EVENT,
'APPWRITE_FUNCTION_EVENT_DATA' : req.env.APPWRITE_FUNCTION_EVENT_DATA,
'APPWRITE_FUNCTION_DATA' : req.env.APPWRITE_FUNCTION_DATA,
'APPWRITE_FUNCTION_USER_ID' : req.env.APPWRITE_FUNCTION_USER_ID,
'APPWRITE_FUNCTION_JWT' : req.env.APPWRITE_FUNCTION_JWT,
'APPWRITE_FUNCTION_PROJECT_ID' : req.env.APPWRITE_FUNCTION_PROJECT_ID,
'CUSTOM_VARIABLE' : req.env.CUSTOM_VARIABLE
});
}
-376
View File
@@ -1,376 +0,0 @@
{
"name": "appwrite-cloud-function-demo",
"version": "0.1.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"ajv": {
"version": "6.12.6",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
"requires": {
"fast-deep-equal": "^3.1.1",
"fast-json-stable-stringify": "^2.0.0",
"json-schema-traverse": "^0.4.1",
"uri-js": "^4.2.2"
}
},
"asn1": {
"version": "0.2.4",
"resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz",
"integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==",
"requires": {
"safer-buffer": "~2.1.0"
}
},
"assert-plus": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
"integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
},
"asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
"integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
},
"aws-sign2": {
"version": "0.7.0",
"resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
"integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg="
},
"aws4": {
"version": "1.11.0",
"resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz",
"integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA=="
},
"bcrypt-pbkdf": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
"integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=",
"requires": {
"tweetnacl": "^0.14.3"
}
},
"caseless": {
"version": "0.12.0",
"resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
"integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw="
},
"combined-stream": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
"requires": {
"delayed-stream": "~1.0.0"
}
},
"core-util-is": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
},
"dashdash": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
"integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=",
"requires": {
"assert-plus": "^1.0.0"
}
},
"delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="
},
"ecc-jsbn": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
"integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=",
"requires": {
"jsbn": "~0.1.0",
"safer-buffer": "^2.1.0"
}
},
"extend": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
"integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="
},
"extsprintf": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
"integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU="
},
"fast-deep-equal": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
},
"fast-json-stable-stringify": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
"integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="
},
"forever-agent": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
"integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE="
},
"form-data": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
"integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==",
"requires": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.6",
"mime-types": "^2.1.12"
}
},
"getpass": {
"version": "0.1.7",
"resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
"integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
"requires": {
"assert-plus": "^1.0.0"
}
},
"har-schema": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
"integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI="
},
"har-validator": {
"version": "5.1.5",
"resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz",
"integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==",
"requires": {
"ajv": "^6.12.3",
"har-schema": "^2.0.0"
}
},
"http-signature": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
"integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=",
"requires": {
"assert-plus": "^1.0.0",
"jsprim": "^1.2.2",
"sshpk": "^1.7.0"
}
},
"is-typedarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
"integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo="
},
"isstream": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
"integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo="
},
"jsbn": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
"integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM="
},
"json-schema": {
"version": "0.2.3",
"resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz",
"integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM="
},
"json-schema-traverse": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="
},
"json-stringify-safe": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
"integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus="
},
"jsprim": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
"integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=",
"requires": {
"assert-plus": "1.0.0",
"extsprintf": "1.3.0",
"json-schema": "0.2.3",
"verror": "1.10.0"
}
},
"lodash": {
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
},
"mime-db": {
"version": "1.44.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz",
"integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg=="
},
"mime-types": {
"version": "2.1.27",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz",
"integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==",
"requires": {
"mime-db": "1.44.0"
}
},
"node-appwrite": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/node-appwrite/-/node-appwrite-1.1.0.tgz",
"integrity": "sha512-ZLOsxmsGry4ZRT63QRbNgUxhYiUzJlQntQL2nKAy6PBL1S/hMCChKrdLIdJv3ytGxPrrIWiDWxXivMeUeCW5KA==",
"requires": {
"request": "^2.88.0",
"request-promise-native": "^1.0.7"
}
},
"oauth-sign": {
"version": "0.9.0",
"resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz",
"integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ=="
},
"performance-now": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
"integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns="
},
"psl": {
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz",
"integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ=="
},
"punycode": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
"integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A=="
},
"qs": {
"version": "6.5.2",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
"integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA=="
},
"request": {
"version": "2.88.2",
"resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz",
"integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==",
"requires": {
"aws-sign2": "~0.7.0",
"aws4": "^1.8.0",
"caseless": "~0.12.0",
"combined-stream": "~1.0.6",
"extend": "~3.0.2",
"forever-agent": "~0.6.1",
"form-data": "~2.3.2",
"har-validator": "~5.1.3",
"http-signature": "~1.2.0",
"is-typedarray": "~1.0.0",
"isstream": "~0.1.2",
"json-stringify-safe": "~5.0.1",
"mime-types": "~2.1.19",
"oauth-sign": "~0.9.0",
"performance-now": "^2.1.0",
"qs": "~6.5.2",
"safe-buffer": "^5.1.2",
"tough-cookie": "~2.5.0",
"tunnel-agent": "^0.6.0",
"uuid": "^3.3.2"
}
},
"request-promise-core": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.4.tgz",
"integrity": "sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw==",
"requires": {
"lodash": "^4.17.19"
}
},
"request-promise-native": {
"version": "1.0.9",
"resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.9.tgz",
"integrity": "sha512-wcW+sIUiWnKgNY0dqCpOZkUbF/I+YPi+f09JZIDa39Ec+q82CpSYniDp+ISgTTbKmnpJWASeJBPZmoxH84wt3g==",
"requires": {
"request-promise-core": "1.1.4",
"stealthy-require": "^1.1.1",
"tough-cookie": "^2.3.3"
}
},
"safe-buffer": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
},
"safer-buffer": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
},
"sshpk": {
"version": "1.16.1",
"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz",
"integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==",
"requires": {
"asn1": "~0.2.3",
"assert-plus": "^1.0.0",
"bcrypt-pbkdf": "^1.0.0",
"dashdash": "^1.12.0",
"ecc-jsbn": "~0.1.1",
"getpass": "^0.1.1",
"jsbn": "~0.1.0",
"safer-buffer": "^2.0.2",
"tweetnacl": "~0.14.0"
}
},
"stealthy-require": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz",
"integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks="
},
"tough-cookie": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz",
"integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==",
"requires": {
"psl": "^1.1.28",
"punycode": "^2.1.1"
}
},
"tunnel-agent": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
"integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=",
"requires": {
"safe-buffer": "^5.0.1"
}
},
"tweetnacl": {
"version": "0.14.5",
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
"integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q="
},
"uri-js": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.0.tgz",
"integrity": "sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g==",
"requires": {
"punycode": "^2.1.0"
}
},
"uuid": {
"version": "3.4.0",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A=="
},
"verror": {
"version": "1.10.0",
"resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
"integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=",
"requires": {
"assert-plus": "^1.0.0",
"core-util-is": "1.0.2",
"extsprintf": "^1.2.0"
}
}
}
}
@@ -1,12 +0,0 @@
echo 'PHP Packaging...'
cp -r $(pwd)/tests/resources/functions/php-fn $(pwd)/tests/resources/functions/packages/php-fn
docker run --rm -v $(pwd)/tests/resources/functions/packages/php-fn:/app -w /app composer:2.0 composer install --ignore-platform-reqs
docker run --rm -v $(pwd)/tests/resources/functions/packages/php-fn:/app -w /app appwrite/env-php-8.0:1.0.0 tar -zcvf code.tar.gz .
mv $(pwd)/tests/resources/functions/packages/php-fn/code.tar.gz $(pwd)/tests/resources/functions/php-fn.tar.gz
rm -r $(pwd)/tests/resources/functions/packages/php-fn
-12
View File
@@ -1,12 +0,0 @@
echo 'PHP Packaging...'
cp -r $(pwd)/tests/resources/functions/php $(pwd)/tests/resources/functions/packages/php
docker run --rm -v $(pwd)/tests/resources/functions/packages/php:/app -w /app composer:2.0 composer install --ignore-platform-reqs
docker run --rm -v $(pwd)/tests/resources/functions/packages/php:/app -w /app appwrite/env-php-8.0:1.0.0 tar -zcvf code.tar.gz .
mv $(pwd)/tests/resources/functions/packages/php/code.tar.gz $(pwd)/tests/resources/functions/php.tar.gz
rm -r $(pwd)/tests/resources/functions/packages/php
@@ -1,10 +0,0 @@
echo 'Timeout Packaging...'
cp -r $(pwd)/tests/resources/functions/timeout $(pwd)/tests/resources/functions/packages/timeout
docker run --rm -v $(pwd)/tests/resources/functions/packages/timeout:/app -w /app appwrite/env-php-8.0:1.0.0 tar -zcvf code.tar.gz .
mv $(pwd)/tests/resources/functions/packages/timeout/code.tar.gz $(pwd)/tests/resources/functions/timeout.tar.gz
rm -r $(pwd)/tests/resources/functions/packages/timeout
Binary file not shown.
+12 -12
View File
@@ -2,17 +2,17 @@
return function ($request, $response) {
$response->json([
'APPWRITE_FUNCTION_ID' => $request->env['APPWRITE_FUNCTION_ID'],
'APPWRITE_FUNCTION_NAME' => $request->env['APPWRITE_FUNCTION_NAME'],
'APPWRITE_FUNCTION_DEPLOYMENT' => $request->env['APPWRITE_FUNCTION_DEPLOYMENT'],
'APPWRITE_FUNCTION_TRIGGER' => $request->env['APPWRITE_FUNCTION_TRIGGER'],
'APPWRITE_FUNCTION_RUNTIME_NAME' => $request->env['APPWRITE_FUNCTION_RUNTIME_NAME'],
'APPWRITE_FUNCTION_RUNTIME_VERSION' => $request->env['APPWRITE_FUNCTION_RUNTIME_VERSION'],
'APPWRITE_FUNCTION_EVENT' => $request->env['APPWRITE_FUNCTION_EVENT'],
'APPWRITE_FUNCTION_EVENT_DATA' => $request->env['APPWRITE_FUNCTION_EVENT_DATA'],
'APPWRITE_FUNCTION_DATA' => $request->env['APPWRITE_FUNCTION_DATA'],
'APPWRITE_FUNCTION_USER_ID' => $request->env['APPWRITE_FUNCTION_USER_ID'],
'APPWRITE_FUNCTION_JWT' => $request->env['APPWRITE_FUNCTION_JWT'],
'APPWRITE_FUNCTION_PROJECT_ID' => $request->env['APPWRITE_FUNCTION_PROJECT_ID'],
'APPWRITE_FUNCTION_ID' => $request['env']['APPWRITE_FUNCTION_ID'],
'APPWRITE_FUNCTION_NAME' => $request['env']['APPWRITE_FUNCTION_NAME'],
'APPWRITE_FUNCTION_DEPLOYMENT' => $request['env']['APPWRITE_FUNCTION_DEPLOYMENT'],
'APPWRITE_FUNCTION_TRIGGER' => $request['env']['APPWRITE_FUNCTION_TRIGGER'],
'APPWRITE_FUNCTION_RUNTIME_NAME' => $request['env']['APPWRITE_FUNCTION_RUNTIME_NAME'],
'APPWRITE_FUNCTION_RUNTIME_VERSION' => $request['env']['APPWRITE_FUNCTION_RUNTIME_VERSION'],
'APPWRITE_FUNCTION_EVENT' => $request['env']['APPWRITE_FUNCTION_EVENT'],
'APPWRITE_FUNCTION_EVENT_DATA' => $request['env']['APPWRITE_FUNCTION_EVENT_DATA'],
'APPWRITE_FUNCTION_DATA' => $request['env']['APPWRITE_FUNCTION_DATA'],
'APPWRITE_FUNCTION_USER_ID' => $request['env']['APPWRITE_FUNCTION_USER_ID'],
'APPWRITE_FUNCTION_JWT' => $request['env']['APPWRITE_FUNCTION_JWT'],
'APPWRITE_FUNCTION_PROJECT_ID' => $request['env']['APPWRITE_FUNCTION_PROJECT_ID'],
]);
};
Binary file not shown.
+8 -8
View File
@@ -2,14 +2,14 @@
return function ($request, $response) {
return $response->json([
'APPWRITE_FUNCTION_ID' => $request->env['APPWRITE_FUNCTION_ID'],
'APPWRITE_FUNCTION_NAME' => $request->env['APPWRITE_FUNCTION_NAME'],
'APPWRITE_FUNCTION_DEPLOYMENT' => $request->env['APPWRITE_FUNCTION_DEPLOYMENT'],
'APPWRITE_FUNCTION_TRIGGER' => $request->env['APPWRITE_FUNCTION_TRIGGER'],
'APPWRITE_FUNCTION_RUNTIME_NAME' => $request->env['APPWRITE_FUNCTION_RUNTIME_NAME'],
'APPWRITE_FUNCTION_RUNTIME_VERSION' => $request->env['APPWRITE_FUNCTION_RUNTIME_VERSION'],
'APPWRITE_FUNCTION_EVENT' => $request->env['APPWRITE_FUNCTION_EVENT'],
'APPWRITE_FUNCTION_EVENT_DATA' => $request->env['APPWRITE_FUNCTION_EVENT_DATA'],
'APPWRITE_FUNCTION_ID' => $request['env']['APPWRITE_FUNCTION_ID'],
'APPWRITE_FUNCTION_NAME' => $request['env']['APPWRITE_FUNCTION_NAME'],
'APPWRITE_FUNCTION_DEPLOYMENT' => $request['env']['APPWRITE_FUNCTION_DEPLOYMENT'],
'APPWRITE_FUNCTION_TRIGGER' => $request['env']['APPWRITE_FUNCTION_TRIGGER'],
'APPWRITE_FUNCTION_RUNTIME_NAME' => $request['env']['APPWRITE_FUNCTION_RUNTIME_NAME'],
'APPWRITE_FUNCTION_RUNTIME_VERSION' => $request['env']['APPWRITE_FUNCTION_RUNTIME_VERSION'],
'APPWRITE_FUNCTION_EVENT' => $request['env']['APPWRITE_FUNCTION_EVENT'],
'APPWRITE_FUNCTION_EVENT_DATA' => $request['env']['APPWRITE_FUNCTION_EVENT_DATA'],
'UNICODE_TEST' => "êä" // TODO: Re-add unicode test to FunctionsCustomServerTest.php
]);
};
Binary file not shown.