mirror of
https://github.com/appwrite/appwrite.git
synced 2026-05-26 13:51:13 +00:00
feat: remove database dependencies from the delete deployment endpoint
This commit is contained in:
+22
-33
@@ -926,44 +926,33 @@ App::post('/v1/functions/:functionId/deployments/:deploymentId/runtime')
|
||||
|
||||
App::delete('/v1/deployments/:deploymentId')
|
||||
->desc('Delete a deployment')
|
||||
->param('deploymentId', '', new UID(), 'Deployment unique ID.')
|
||||
->inject('projectId')
|
||||
->param('deploymentId', '', new UID(), 'Deployment unique ID.', false)
|
||||
->param('buildIds', [], new ArrayList(new Text(0), 100), 'List of build IDs to delete.', false)
|
||||
->inject('response')
|
||||
->action(function (string $deploymentId, string $projectId, Response $response) use ($orchestrationPool) {
|
||||
->action(function (string $deploymentId, array $buildIds, Response $response) use ($orchestrationPool) {
|
||||
|
||||
Console::info('Deleting deployment: ' . $deploymentId);
|
||||
global $register;
|
||||
go(function () use ($projectId, $orchestrationPool, $register, $deploymentId) {
|
||||
try {
|
||||
$orchestration = $orchestrationPool->get();
|
||||
// Remove the container of the deployment
|
||||
$orchestration->remove('appwrite-function-' . $deploymentId , true);
|
||||
Console::success('Removed container for deployment: ' . $deploymentId);
|
||||
$orchestration = $orchestrationPool->get();
|
||||
|
||||
$db = $register->get('dbPool')->get();
|
||||
$redis = $register->get('redisPool')->get();
|
||||
$cache = new Cache(new RedisCache($redis));
|
||||
$dbForProject = new Database(new MariaDB($db), $cache);
|
||||
$dbForProject->setDefaultDatabase(App::getEnv('_APP_DB_SCHEMA', 'appwrite'));
|
||||
$dbForProject->setNamespace('_project_' . $projectId);
|
||||
// Remove the container of the deployment
|
||||
$status = $orchestration->remove('appwrite-function-' . $deploymentId , true);
|
||||
if ($status) {
|
||||
Console::success('Removed container for deployment: ' . $deploymentId);
|
||||
} else {
|
||||
Console::error('Failed to remove container for deployment: ' . $deploymentId);
|
||||
}
|
||||
|
||||
$builds = $dbForProject->find('builds', [
|
||||
new Query('deploymentId', Query::TYPE_EQUAL, [$deploymentId]),
|
||||
new Query('status', Query::TYPE_EQUAL, ['building'])
|
||||
], 999);
|
||||
|
||||
// Remove all the build containers
|
||||
foreach ($builds as $build) {
|
||||
$orchestration->remove('build-stage-' . $build['$id'], true);
|
||||
Console::success("Removed build container: $build for deployment: " . $deploymentId);
|
||||
}
|
||||
} catch (\Throwable $th) {
|
||||
Console::error($th->getMessage());
|
||||
} finally {
|
||||
$orchestrationPool->put($orchestration);
|
||||
$register->get('dbPool')->put($db);
|
||||
$register->get('redisPool')->put($redis);
|
||||
// Remove all the build containers
|
||||
foreach ($buildIds as $buildId) {
|
||||
$status = $orchestration->remove('build-stage-' . $buildId, true);
|
||||
if ($status) {
|
||||
Console::success("Removed build container: $buildId for deployment: " . $deploymentId);
|
||||
} else {
|
||||
Console::error("Failed to remove build container: $buildId for deployment: " . $deploymentId);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$orchestrationPool->put($orchestration);
|
||||
|
||||
$response
|
||||
->setStatusCode(Response::STATUS_CODE_OK)
|
||||
|
||||
+185
-21
@@ -389,33 +389,34 @@ class DeletesV1 extends Worker
|
||||
{
|
||||
$dbForProject = $this->getProjectDB($projectId);
|
||||
|
||||
$builds = $dbForProject->find('builds', [
|
||||
new Query('deploymentId', Query::TYPE_EQUAL, [$document->getId()])
|
||||
], 999);
|
||||
|
||||
$buildIds = [];
|
||||
foreach ($builds as $build) {
|
||||
$buildIds[] = $build['$id'];
|
||||
}
|
||||
/**
|
||||
* Request executor to delete the deployment containers
|
||||
*/
|
||||
try {
|
||||
$ch = \curl_init();
|
||||
\curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE');
|
||||
// TODO: Implement coroutines.
|
||||
\curl_setopt($ch, CURLOPT_URL, "http://appwrite-executor/v1/deployments/{$document->getId()}");
|
||||
\curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
\curl_setopt($ch, CURLOPT_HTTPHEADER, [
|
||||
'Content-Type: application/json',
|
||||
'x-appwrite-project: '. $projectId,
|
||||
'x-appwrite-executor-key: '. App::getEnv('_APP_EXECUTOR_SECRET', '')
|
||||
]);
|
||||
$route = "/deployments/{$document->getId()}";
|
||||
$headers = [
|
||||
'content-Type' => 'application/json',
|
||||
'x-appwrite-project' => $projectId,
|
||||
'x-appwrite-executor-key' => App::getEnv('_APP_EXECUTOR_SECRET', '')
|
||||
];
|
||||
$params = [
|
||||
'buildIds' => $buildIds ?? []
|
||||
];
|
||||
|
||||
$executorResponse = \curl_exec($ch);
|
||||
$error = \curl_error($ch);
|
||||
if (!empty($error)) {
|
||||
throw new Exception($error, 500);
|
||||
}
|
||||
$response = $this->call(self::METHOD_DELETE, $route, $headers, $params, true, 30);
|
||||
$status = $response['headers']['status-code'];
|
||||
if ($status >= 400) {
|
||||
throw new \Exception('Error deleting deplyoment: ' . $document->getId() , $status);
|
||||
}
|
||||
|
||||
$statusCode = \curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
if ($statusCode >= 400) {
|
||||
throw new Exception('Executor error: ' . $executorResponse, $statusCode);
|
||||
}
|
||||
|
||||
\curl_close($ch);
|
||||
} catch (Throwable $th) {
|
||||
Console::error($th->getMessage());
|
||||
}
|
||||
@@ -565,4 +566,167 @@ class DeletesV1 extends Worker
|
||||
Console::info("No certificate files found for {$domain}");
|
||||
}
|
||||
}
|
||||
|
||||
const METHOD_GET = 'GET';
|
||||
const METHOD_POST = 'POST';
|
||||
const METHOD_PUT = 'PUT';
|
||||
const METHOD_PATCH = 'PATCH';
|
||||
const METHOD_DELETE = 'DELETE';
|
||||
const METHOD_HEAD = 'HEAD';
|
||||
const METHOD_OPTIONS = 'OPTIONS';
|
||||
const METHOD_CONNECT = 'CONNECT';
|
||||
const METHOD_TRACE = 'TRACE';
|
||||
|
||||
protected $selfSigned = false;
|
||||
private $endpoint = 'http://appwrite-executor/v1';
|
||||
protected $headers = [
|
||||
'content-type' => '',
|
||||
];
|
||||
|
||||
/**
|
||||
* Call
|
||||
*
|
||||
* Make an API call
|
||||
*
|
||||
* @param string $method
|
||||
* @param string $path
|
||||
* @param array $params
|
||||
* @param array $headers
|
||||
* @param bool $decode
|
||||
* @return array|string
|
||||
* @throws Exception
|
||||
*/
|
||||
public function call(string $method, string $path = '', array $headers = [], array $params = [], bool $decode = true, int $timeout = 15)
|
||||
{
|
||||
$headers = array_merge($this->headers, $headers);
|
||||
$ch = curl_init($this->endpoint . $path . (($method == self::METHOD_GET && !empty($params)) ? '?' . http_build_query($params) : ''));
|
||||
$responseHeaders = [];
|
||||
$responseStatus = -1;
|
||||
$responseType = '';
|
||||
$responseBody = '';
|
||||
|
||||
switch ($headers['content-type']) {
|
||||
case 'application/json':
|
||||
$query = json_encode($params);
|
||||
break;
|
||||
|
||||
case 'multipart/form-data':
|
||||
$query = $this->flatten($params);
|
||||
break;
|
||||
|
||||
default:
|
||||
$query = http_build_query($params);
|
||||
break;
|
||||
}
|
||||
|
||||
foreach ($headers as $i => $header) {
|
||||
$headers[] = $i . ':' . $header;
|
||||
unset($headers[$i]);
|
||||
}
|
||||
|
||||
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
||||
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
|
||||
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36');
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
|
||||
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 0);
|
||||
curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
|
||||
curl_setopt($ch, CURLOPT_HEADERFUNCTION, function ($curl, $header) use (&$responseHeaders) {
|
||||
$len = strlen($header);
|
||||
$header = explode(':', $header, 2);
|
||||
|
||||
if (count($header) < 2) { // ignore invalid headers
|
||||
return $len;
|
||||
}
|
||||
|
||||
$responseHeaders[strtolower(trim($header[0]))] = trim($header[1]);
|
||||
|
||||
return $len;
|
||||
});
|
||||
|
||||
if ($method != self::METHOD_GET) {
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $query);
|
||||
}
|
||||
|
||||
// Allow self signed certificates
|
||||
if ($this->selfSigned) {
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
||||
}
|
||||
|
||||
$responseBody = curl_exec($ch);
|
||||
$responseType = $responseHeaders['content-type'] ?? '';
|
||||
$responseStatus = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
|
||||
if($decode) {
|
||||
switch (substr($responseType, 0, strpos($responseType, ';'))) {
|
||||
case 'application/json':
|
||||
$json = json_decode($responseBody, true);
|
||||
|
||||
if ($json === null) {
|
||||
throw new Exception('Failed to parse response: '.$responseBody);
|
||||
}
|
||||
|
||||
$responseBody = $json;
|
||||
$json = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ((curl_errno($ch)/* || 200 != $responseStatus*/)) {
|
||||
throw new Exception(curl_error($ch) . ' with status code ' . $responseStatus, $responseStatus);
|
||||
}
|
||||
|
||||
curl_close($ch);
|
||||
|
||||
$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
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse Cookie String
|
||||
*
|
||||
* @param string $cookie
|
||||
* @return array
|
||||
*/
|
||||
public function parseCookie(string $cookie): array
|
||||
{
|
||||
$cookies = [];
|
||||
|
||||
parse_str(strtr($cookie, array('&' => '%26', '+' => '%2B', ';' => '&')), $cookies);
|
||||
|
||||
return $cookies;
|
||||
}
|
||||
|
||||
/**
|
||||
* Flatten params array to PHP multiple format
|
||||
*
|
||||
* @param array $data
|
||||
* @param string $prefix
|
||||
* @return array
|
||||
*/
|
||||
protected function flatten(array $data, string $prefix = ''): array
|
||||
{
|
||||
$output = [];
|
||||
|
||||
foreach ($data as $key => $value) {
|
||||
$finalKey = $prefix ? "{$prefix}[{$key}]" : $key;
|
||||
|
||||
if (is_array($value)) {
|
||||
$output += $this->flatten($value, $finalKey); // @todo: handle name collision here if needed
|
||||
} else {
|
||||
$output[$finalKey] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user