From 4ae5e82d6facd2fdfe2cee6fa12954ed60a7c1de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Thu, 5 Sep 2024 13:23:24 +0000 Subject: [PATCH] Fix logging behaviour; new tests --- app/controllers/general.php | 5 +- src/Appwrite/Platform/Workers/Functions.php | 4 +- .../Functions/FunctionsCustomServerTest.php | 143 ++++++++++++++++++ 3 files changed, 145 insertions(+), 7 deletions(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index ff670c68ca..c69bbbf32d 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -350,10 +350,7 @@ function router(App $utopia, Database $dbForConsole, callable $getProjectDB, Swo ->trigger() ; - if ($function->getAttribute('logging')) { - /** @var Document $execution */ - $execution = Authorization::skip(fn () => $dbForProject->createDocument('executions', $execution)); - } + $execution = Authorization::skip(fn () => $dbForProject->createDocument('executions', $execution)); } $execution->setAttribute('logs', ''); diff --git a/src/Appwrite/Platform/Workers/Functions.php b/src/Appwrite/Platform/Workers/Functions.php index 7e82c9c0c6..9e5f2aa7f8 100644 --- a/src/Appwrite/Platform/Workers/Functions.php +++ b/src/Appwrite/Platform/Workers/Functions.php @@ -260,9 +260,7 @@ class Functions extends Action 'search' => implode(' ', [$function->getId(), $executionId]), ]); - if ($function->getAttribute('logging')) { - $execution = $dbForProject->createDocument('executions', $execution); - } + $execution = $dbForProject->createDocument('executions', $execution); if ($execution->isEmpty()) { throw new Exception('Failed to create execution'); diff --git a/tests/e2e/Services/Functions/FunctionsCustomServerTest.php b/tests/e2e/Services/Functions/FunctionsCustomServerTest.php index 912a7a3f2c..c3cfb7c991 100644 --- a/tests/e2e/Services/Functions/FunctionsCustomServerTest.php +++ b/tests/e2e/Services/Functions/FunctionsCustomServerTest.php @@ -2666,4 +2666,147 @@ class FunctionsCustomServerTest extends Scope $this->assertEquals(204, $response['headers']['status-code']); } + + public function testFunctionLogging() + { + // Preparations: Create Function + $folder = 'node'; + $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'], + ], $this->getHeaders()), [ + 'functionId' => ID::unique(), + 'runtime' => 'node-18.0', + 'name' => 'Logging Test', + 'entrypoint' => 'index.js', + 'logging' => false, + 'execute' => ['any'] + ]); + + $this->assertEquals(201, $function['headers']['status-code']); + $this->assertFalse($function['body']['logging']); + $this->assertNotEmpty($function['body']['$id']); + + $functionId = $function['body']['$id']; + + $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()), [ + 'code' => new CURLFile($code, 'application/x-gzip', basename($code)), + 'activate' => true + ]); + + $this->assertEquals(202, $deployment['headers']['status-code']); + $this->assertNotEmpty($deployment['body']['$id']); + + $deploymentId = $deployment['body']['$id'] ?? ''; + + $this->awaitDeploymentIsBuilt($functionId, $deploymentId, checkForSuccess: false); + + // Sync Executions test + $execution = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/executions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), []); + + $this->assertEquals(201, $execution['headers']['status-code']); + $this->assertEmpty($execution['body']['logs']); + $this->assertEmpty($execution['body']['errors']); + + // Async Executions test + $execution = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/executions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'async' => true + ]); + + $this->assertEquals(202, $execution['headers']['status-code']); + $this->assertEmpty($execution['body']['logs']); + $this->assertEmpty($execution['body']['errors']); + $this->assertNotEmpty($execution['body']['$id']); + + $executionId = $execution['body']['$id']; + + sleep(5); + + $execution = $this->client->call(Client::METHOD_GET, '/functions/' . $functionId . '/executions/' . $executionId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $execution['headers']['status-code']); + $this->assertEquals('completed', $execution['body']['status']); + $this->assertEmpty($execution['body']['logs']); + $this->assertEmpty($execution['body']['errors']); + + // Domain Executions test + $rules = $this->client->call(Client::METHOD_GET, '/proxy/rules', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::equal('resourceId', [$functionId])->toString(), + Query::equal('resourceType', ['function'])->toString(), + ], + ]); + + $this->assertEquals(200, $rules['headers']['status-code']); + $this->assertNotEmpty($rules['body']['rules'][0]['domain']); + + $domain = $rules['body']['rules'][0]['domain']; + + $proxyClient = new Client(); + $proxyClient->setEndpoint('http://' . $domain); + + $response = $proxyClient->call(Client::METHOD_GET, '/', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'] + ])); + + $this->assertEquals(200, $response['headers']['status-code']); + + $executions = $this->client->call(Client::METHOD_GET, '/functions/' . $functionId . '/executions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::limit(1)->toString(), + Query::orderDesc('$id')->toString(), + ] + ]); + + $this->assertEquals(200, $executions['headers']['status-code']); + $this->assertCount(1, $executions['body']['executions']); + $this->assertEmpty($executions['body']['executions'][0]['logs']); + $this->assertEmpty($executions['body']['executions'][0]['errors']); + + // Ensure executions count + $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(200, $executions['headers']['status-code']); + $this->assertCount(3, $executions['body']['executions']); + + // Double check logs and errors are empty + foreach ($executions['body']['executions'] as $execution) { + $this->assertEmpty($execution['logs']); + $this->assertEmpty($execution['errors']); + } + + // 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']); + } }