1
0
Fork 0
mirror of synced 2024-06-01 18:39:57 +12:00

feat: add 406 status code

This commit is contained in:
Christy Jacob 2022-02-18 04:43:04 +04:00
parent 281e306d14
commit f752807790
4 changed files with 145 additions and 107 deletions

View file

@ -20,6 +20,7 @@ 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;
@ -118,16 +119,18 @@ App::post('/v1/runtimes')
->desc("Create a new runtime server")
->param('runtimeId', '', new Text(62), '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('workdir', '', new Text(256), 'Working directory')
->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, string $workdir, $orchestrationPool, $activeRuntimes, Response $response) {
->action(function (string $runtimeId, string $source, string $destination, array $vars, array $commands, string $runtime, string $network, string $baseImage, bool $remove, string $workdir, $orchestrationPool, $activeRuntimes, Response $response) {
$container = 'r-' . $runtimeId;
@ -172,7 +175,11 @@ App::post('/v1/runtimes')
* Create container
*/
$orchestration = $orchestrationPool->get();
$container = 'b-' . $runtimeId;
$container = 'r-' . $runtimeId;
$secret = \bin2hex(\random_bytes(16));
$vars = \array_merge($vars, [
'INTERNAL_RUNTIME_KEY' => $secret
]);
$vars = array_map(fn ($v) => strval($v), $vars);
$orchestration
->setCpus(App::getEnv('_APP_FUNCTIONS_CPUS', 1))
@ -190,11 +197,11 @@ App::post('/v1/runtimes')
'openruntimes-created' => strval($buildStart),
'openruntimes-runtime' => $runtime,
],
command: [
'tail',
'-f',
'/dev/null'
],
// command: [
// 'tail',
// '-f',
// '/dev/null'
// ],
mountFolder: \dirname($tmpSource),
workdir: $workdir,
volumes: [
@ -206,6 +213,10 @@ App::post('/v1/runtimes')
throw new Exception('Failed to create build container', 500);
}
if (!empty($network)) {
$orchestration->networkConnect($container, $network);
}
/**
* Execute any commands if they were provided
*/
@ -247,7 +258,7 @@ App::post('/v1/runtimes')
$build['outputPath'] = $outputPath;
}
if ($buildStdout === '') {
if (empty($buildStdout)) {
$buildStdout = 'Build Successful!';
}
@ -261,86 +272,91 @@ App::post('/v1/runtimes')
'duration' => $buildEnd - $buildStart,
]);
if (!$remove) {
$activeRuntimes->set($container, [
'id' => $buildId,
'name' => $container,
'created' => $buildStart,
'updated' => $buildEnd,
'status' => 'Up ' . \round($buildEnd - $buildStart, 2) . 's',
'key' => $secret,
]);
}
Console::success('Build Stage completed in ' . ($buildEnd - $buildStart) . ' seconds');
} catch (Throwable $th) {
Console::error('Build failed: ' . $th->getMessage());
throw new Exception($th->getMessage(), 500);
} finally {
if (!empty($buildId)) {
if (!empty($buildId) && $remove) {
$orchestration->remove($buildId, 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);
};
// /** Create runtime server */
// try {
// $orchestration = $orchestrationPool->get();
// /**
// * Copy code files from source to a temporary location on the executor
// */
// $buffer = $device->read($source);
// if(!$device->write($tmpSource, $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
]);
// /**
// * Launch Runtime
// */
// $container = 'r-' . $runtimeId;
// $secret = \bin2hex(\random_bytes(16));
// $vars = \array_merge($vars, [
// 'INTERNAL_RUNTIME_KEY' => $secret
// ]);
$executionStart = \microtime(true);
$executionTime = \time();
// $executionStart = \microtime(true);
// $executionTime = \time();
$vars = array_map(fn ($v) => strval($v), $vars);
// $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));
// $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),
);
// $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($tmpSource),
// );
if (empty($id)) {
throw new Exception('Failed to create runtime', 500);
}
// if (empty($id)) {
// throw new Exception('Failed to create runtime', 500);
// }
$orchestration->networkConnect($container, App::getEnv('_APP_EXECUTOR_RUNTIME_NETWORK', 'openruntimes'));
// $orchestration->networkConnect($container, App::getEnv('_APP_EXECUTOR_RUNTIME_NETWORK', 'openruntimes'));
$executionEnd = \microtime(true);
// $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);
}
// 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)
@ -502,7 +518,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 = [];
@ -567,15 +583,16 @@ App::setResource('activeRuntimes', fn() => $activeRuntimes);
App::error(function ($error, $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
@ -594,6 +611,8 @@ App::error(function ($error, $response) {
'version' => App::getEnv('OPENRUNTIMES_VERSION', 'UNKNOWN'),
];
var_dump($output);
$response
->addHeader('Cache-Control', 'no-cache, no-store, must-revalidate')
->addHeader('Expires', '0')

View file

@ -117,10 +117,12 @@ 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 && \

12
composer.lock generated
View file

@ -2252,16 +2252,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 +2295,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",

View file

@ -3,7 +3,9 @@
namespace Executor;
use Exception;
use phpDocumentor\Reflection\DocBlock\Tags\Var_;
use Utopia\App;
use Utopia\CLI\Console;
class Executor
{
@ -34,10 +36,13 @@ class Executor
string $functionId,
string $deploymentId,
string $projectId,
string $source,
string $source,
string $runtime,
string $baseImage,
string $workdir,
bool $remove = false,
string $workdir = '',
string $destination = '',
string $network = '',
array $vars = [],
array $commands = []
) {
@ -49,14 +54,18 @@ class Executor
$params = [
'runtimeId' => "$projectId-$deploymentId",
'source' => $source,
'destination' => APP_STORAGE_BUILDS . "/app-$projectId",
'destination' => $destination,
'runtime' => $runtime,
'baseImage' => $baseImage,
'workdir' => $workdir,
'network' => empty($network) ? App::getEnv('_APP_EXECUTOR_RUNTIME_NETWORK', 'openruntimes') : $network,
'vars' => $vars,
'remove' => $remove,
'commands' => $commands
];
var_dump($params);
$response = $this->call(self::METHOD_POST, $route, $headers, $params, true, 30);
$status = $response['headers']['status-code'];
@ -131,35 +140,47 @@ class Executor
$response = $this->call(self::METHOD_POST, $route, $headers, $params, true, 30);
$status = $response['headers']['status-code'];
if ($status >= 400) {
switch ($status) {
case 404:
$response = $this->createRuntime($functionId, $deploymentId, $projectId, $path, $runtime, $baseImage, '', $vars);
/** Try to create the execution once more */
$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);
}
break;
case 425:
for ($attempts = 0; $attempts < 3; $attempts++) {
sleep(1);
for ($attempts = 0; $attempts < 3; $attempts++) {
switch ($status) {
case 404:
Console::error("Runtime not found. Creating runtine");
$response = $this->createRuntime(
functionId: $functionId,
deploymentId: $deploymentId,
projectId: $projectId,
source: $path,
runtime: $runtime,
baseImage: $baseImage,
vars: $vars,
commands: []
);
/** Try to create the execution once more */
Console::error("Creating execution");
$response = $this->call(self::METHOD_POST, $route, $headers, $params, true, 30);
$status = $response['headers']['status-code'];
var_dump($status);
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) {
break;
}
if ($status !== 425) {
throw new Exception($response['body']['message'], $status);
}
}
throw new Exception($response['body']['message'], 503);
default:
if ($status < 400) {
return $response['body'];
}
if ($status != 406) {
throw new \Exception($response['body']['message'], $status);
}
sleep(1);
}
throw new Exception($response['body']['message'], 503);
}
return $response['body'];
@ -262,10 +283,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