From c8f9bbc34bf59ac9f2a8120443cad3c85aa08690 Mon Sep 17 00:00:00 2001 From: kodumbeats Date: Tue, 30 Mar 2021 16:36:07 -0400 Subject: [PATCH 1/6] Outline calls to docker socket --- app/workers/functions.php | 83 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 80 insertions(+), 3 deletions(-) diff --git a/app/workers/functions.php b/app/workers/functions.php index 87e3a8624..b18d6178a 100644 --- a/app/workers/functions.php +++ b/app/workers/functions.php @@ -16,7 +16,7 @@ require_once __DIR__.'/../init.php'; Console::title('Functions V1 Worker'); -Runtime::setHookFlags(SWOOLE_HOOK_ALL); +// Runtime::setHookFlags(SWOOLE_HOOK_ALL); Console::success(APP_NAME.' functions worker v1 has started'); @@ -343,6 +343,14 @@ class FunctionsV1 'APPWRITE_FUNCTION_EVENT_PAYLOAD' => $payload, ]); + $tmpvars = $vars; + \array_walk($tmpvars, function (&$value, $key) { + $key = $this->filterEnvKey($key); + $value = \escapeshellarg((empty($value)) ? 'null' : $value); + // $value = "--env {$key}={$value}"; + $value = "{$key}={$value}"; + }); + \array_walk($vars, function (&$value, $key) { $key = $this->filterEnvKey($key); $value = \escapeshellarg((empty($value)) ? 'null' : $value); @@ -441,10 +449,79 @@ class FunctionsV1 $stdout = ''; $stderr = ''; + + $executionStart = \microtime(true); + $envs = \array_merge(\array_values($tmpvars), ["executionStart={$executionStart}"]); + var_dump($envs); + + /* + * Create execution via Docker API + */ + $ch = \curl_init(); + var_dump($executionStart); + + \curl_setopt($ch, CURLOPT_URL, "http://localhost/containers/{$container}/exec"); + \curl_setopt($ch, CURLOPT_UNIX_SOCKET_PATH, '/var/run/docker.sock'); + \curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + \curl_setopt($ch, CURLOPT_POST, 1); + \curl_setopt($ch, CURLOPT_POSTFIELDS, [ + "Env" => $envs, + "Cmd" => $command, + ]); + + $headers = array(); + $headers[] = 'Content-Type: application/json'; + \curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); + + $result = \curl_exec($ch); + var_dump($result); + + if (\curl_errno($ch)) { + echo 'Error:' . \curl_error($ch); + } + + \curl_close($ch); + + /* + * Query for event 'exec_die' + */ + // $ch = \curl_init(); +// + // $URL = 'http://localhost/events'; + // $params = [ + // 'filter' => json_encode([ + // 'type' => 'container', + // 'container' => $container, + // 'event' => 'exec_die', + // ]), + // 'since' => \floor($executionStart) + // 'until' => $executionStart + +App::getEnv('_APP_FUNCTIONS_TIMEOUT', 900) + // ]; + // $URL = $URL . '?' . \http_build_query($params); + // var_dump($URL); +// + // \curl_setopt($ch, CURLOPT_URL, $URL); + // \curl_setopt($ch, CURLOPT_UNIX_SOCKET_PATH, '/var/run/docker.sock'); + // \curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + + // $headers = array(); + // $headers[] = 'Content-Type: application/json'; + // \curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); + + // $result = \curl_exec($ch); +// + // if (\curl_errno($ch)) { + // echo 'Error:' . \curl_error($ch); + // } + // var_dump($result); + // var_dump(\microtime(true) - $executionStart); +// + // \curl_close($ch); + - $exitCode = Console::execute("docker exec ".\implode(" ", $vars)." {$container} {$command}" - , '', $stdout, $stderr, $function->getAttribute('timeout', (int) App::getEnv('_APP_FUNCTIONS_TIMEOUT', 900))); + // $exitCode = Console::execute("docker exec ".\implode(" ", $vars)." {$container} {$command}" + // , '', $stdout, $stderr, $function->getAttribute('timeout', (int) App::getEnv('_APP_FUNCTIONS_TIMEOUT', 900))); $executionEnd = \microtime(true); $executionTime = ($executionEnd - $executionStart); From 967d661a59fcac24d2b5a35d8217761a14997190 Mon Sep 17 00:00:00 2001 From: kodumbeats Date: Tue, 30 Mar 2021 18:13:44 -0400 Subject: [PATCH 2/6] Pass Content-Length header --- app/workers/functions.php | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/app/workers/functions.php b/app/workers/functions.php index b18d6178a..016d7ded6 100644 --- a/app/workers/functions.php +++ b/app/workers/functions.php @@ -453,26 +453,34 @@ class FunctionsV1 $executionStart = \microtime(true); $envs = \array_merge(\array_values($tmpvars), ["executionStart={$executionStart}"]); - var_dump($envs); + // var_dump($envs); /* * Create execution via Docker API */ $ch = \curl_init(); - var_dump($executionStart); \curl_setopt($ch, CURLOPT_URL, "http://localhost/containers/{$container}/exec"); \curl_setopt($ch, CURLOPT_UNIX_SOCKET_PATH, '/var/run/docker.sock'); \curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); \curl_setopt($ch, CURLOPT_POST, 1); - \curl_setopt($ch, CURLOPT_POSTFIELDS, [ - "Env" => $envs, - "Cmd" => $command, - ]); - $headers = array(); - $headers[] = 'Content-Type: application/json'; + $body = array( + "Env" => $envs, + "Cmd" => $command + ); + var_dump($body); + $body = json_encode($body); + var_dump($body); + + \curl_setopt($ch, CURLOPT_POSTFIELDS, $body); + + $headers = [ + 'Content-Type: application/json', + 'Content-Length: ' . \strlen($body) + ]; \curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); + var_dump($headers); $result = \curl_exec($ch); var_dump($result); From af6b90ba8331d49bfdc8b69a47dbc6ccf4f54528 Mon Sep 17 00:00:00 2001 From: kodumbeats Date: Tue, 30 Mar 2021 20:49:23 -0400 Subject: [PATCH 3/6] Testing if the exec must be started --- app/workers/functions.php | 78 +++++++++++++++++++++++++++++---------- 1 file changed, 58 insertions(+), 20 deletions(-) diff --git a/app/workers/functions.php b/app/workers/functions.php index 016d7ded6..50392ce67 100644 --- a/app/workers/functions.php +++ b/app/workers/functions.php @@ -467,7 +467,9 @@ class FunctionsV1 $body = array( "Env" => $envs, - "Cmd" => $command + "Cmd" => \explode(' ', $command), + "AttachStdout" => true, + "AttachStderr" => true ); var_dump($body); $body = json_encode($body); @@ -483,6 +485,9 @@ class FunctionsV1 var_dump($headers); $result = \curl_exec($ch); + $resultDecoded = json_decode($result, true); + $execId = $resultDecoded['Id']; + var_dump($result); if (\curl_errno($ch)) { @@ -491,12 +496,46 @@ class FunctionsV1 \curl_close($ch); + + + /* + * Maybe just creating the function doesnt start it? + * Currently throws errors + */ + + $ch = \curl_init(); + $URL = "http://localhost/exec/{$execId}/start"; + \curl_setopt($ch, CURLOPT_URL, $URL); + \curl_setopt($ch, CURLOPT_UNIX_SOCKET_PATH, '/var/run/docker.sock'); + \curl_setopt($ch, CURLOPT_POST, 1); + \curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([])); + \curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + + $headers = array(); + $headers[] = 'Content-Type: application/json'; + \curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); + + $result = \curl_exec($ch); + + if (\curl_errno($ch)) { + echo 'Error:' . \curl_error($ch); + } + var_dump($result); + + \curl_close($ch); + + + + + + + sleep(5); /* * Query for event 'exec_die' */ - // $ch = \curl_init(); -// - // $URL = 'http://localhost/events'; + $ch = \curl_init(); + + $URL = "http://localhost/exec/{$execId}/json"; // $params = [ // 'filter' => json_encode([ // 'type' => 'container', @@ -508,24 +547,23 @@ class FunctionsV1 // ]; // $URL = $URL . '?' . \http_build_query($params); // var_dump($URL); -// - // \curl_setopt($ch, CURLOPT_URL, $URL); - // \curl_setopt($ch, CURLOPT_UNIX_SOCKET_PATH, '/var/run/docker.sock'); - // \curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); - // $headers = array(); - // $headers[] = 'Content-Type: application/json'; - // \curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); + \curl_setopt($ch, CURLOPT_URL, $URL); + \curl_setopt($ch, CURLOPT_UNIX_SOCKET_PATH, '/var/run/docker.sock'); + \curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); - // $result = \curl_exec($ch); -// - // if (\curl_errno($ch)) { - // echo 'Error:' . \curl_error($ch); - // } - // var_dump($result); - // var_dump(\microtime(true) - $executionStart); -// - // \curl_close($ch); + $headers = array(); + $headers[] = 'Content-Type: application/json'; + \curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); + + $result = \curl_exec($ch); + + if (\curl_errno($ch)) { + echo 'Error:' . \curl_error($ch); + } + var_dump($result); + + \curl_close($ch); // $exitCode = Console::execute("docker exec ".\implode(" ", $vars)." {$container} {$command}" From 1f4529d4e43ec9d6666ad2f76e45cadc8f5b59d4 Mon Sep 17 00:00:00 2001 From: kodumbeats Date: Wed, 31 Mar 2021 10:58:04 -0400 Subject: [PATCH 4/6] Start execution and get status code --- app/workers/functions.php | 70 ++++++++++++++++++--------------------- 1 file changed, 32 insertions(+), 38 deletions(-) diff --git a/app/workers/functions.php b/app/workers/functions.php index 50392ce67..68b62c8cb 100644 --- a/app/workers/functions.php +++ b/app/workers/functions.php @@ -450,10 +450,9 @@ class FunctionsV1 $stderr = ''; - $executionStart = \microtime(true); - $envs = \array_merge(\array_values($tmpvars), ["executionStart={$executionStart}"]); - // var_dump($envs); + $envs = array_values($tmpvars); + $envs[] = "executionStart={$executionStart}"; /* * Create execution via Docker API @@ -465,30 +464,26 @@ class FunctionsV1 \curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); \curl_setopt($ch, CURLOPT_POST, 1); - $body = array( + $body = array( "Env" => $envs, "Cmd" => \explode(' ', $command), "AttachStdout" => true, "AttachStderr" => true ); - var_dump($body); $body = json_encode($body); - var_dump($body); - \curl_setopt($ch, CURLOPT_POSTFIELDS, $body); + \curl_setopt($ch, CURLOPT_POSTFIELDS, $body); - $headers = [ + $headers = [ 'Content-Type: application/json', 'Content-Length: ' . \strlen($body) ]; \curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); - var_dump($headers); $result = \curl_exec($ch); $resultDecoded = json_decode($result, true); $execId = $resultDecoded['Id']; - var_dump($result); if (\curl_errno($ch)) { echo 'Error:' . \curl_error($ch); @@ -497,10 +492,8 @@ class FunctionsV1 \curl_close($ch); - /* - * Maybe just creating the function doesnt start it? - * Currently throws errors + * Start execution without detatching - will receive stdout/stderr as response */ $ch = \curl_init(); @@ -508,46 +501,44 @@ class FunctionsV1 \curl_setopt($ch, CURLOPT_URL, $URL); \curl_setopt($ch, CURLOPT_UNIX_SOCKET_PATH, '/var/run/docker.sock'); \curl_setopt($ch, CURLOPT_POST, 1); - \curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([])); + \curl_setopt($ch, CURLOPT_POSTFIELDS, '{}'); \curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); - $headers = array(); - $headers[] = 'Content-Type: application/json'; + $headers = [ + 'Content-Type: application/json', + 'Content-Length: 2', + ]; \curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); $result = \curl_exec($ch); + var_dump($result); if (\curl_errno($ch)) { echo 'Error:' . \curl_error($ch); } - var_dump($result); \curl_close($ch); + sleep(1); - - - - - sleep(5); + // TODO@kodumbeats: set up listener for /events for exec_start and exec_die + // We need this to get accurate + // $params = [ + // 'filter' => json_encode([ + // 'type' => 'container', + // 'container' => $container, + // 'event' => 'exec_die', + // ]), + // 'since' => \floor($executionStart) + // 'until' => $executionStart + +App::getEnv('_APP_FUNCTIONS_TIMEOUT', 900) + // ]; + // $URL = $URL . '?' . \http_build_query($params); /* - * Query for event 'exec_die' + * Get execution details */ $ch = \curl_init(); $URL = "http://localhost/exec/{$execId}/json"; - // $params = [ - // 'filter' => json_encode([ - // 'type' => 'container', - // 'container' => $container, - // 'event' => 'exec_die', - // ]), - // 'since' => \floor($executionStart) - // 'until' => $executionStart + +App::getEnv('_APP_FUNCTIONS_TIMEOUT', 900) - // ]; - // $URL = $URL . '?' . \http_build_query($params); - // var_dump($URL); - \curl_setopt($ch, CURLOPT_URL, $URL); \curl_setopt($ch, CURLOPT_UNIX_SOCKET_PATH, '/var/run/docker.sock'); \curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); @@ -557,11 +548,12 @@ class FunctionsV1 \curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); $result = \curl_exec($ch); + $execData = json_decode($result, true); // Can get the exit code from this call. + $exitCode = $execData['ExitCode']; if (\curl_errno($ch)) { echo 'Error:' . \curl_error($ch); } - var_dump($result); \curl_close($ch); @@ -581,8 +573,10 @@ class FunctionsV1 'tagId' => $tag->getId(), 'status' => $functionStatus, 'exitCode' => $exitCode, - 'stdout' => \mb_substr($stdout, -4000), // log last 4000 chars output - 'stderr' => \mb_substr($stderr, -4000), // log last 4000 chars output + // 'stdout' => \mb_substr($stdout, -4000), // log last 4000 chars output + 'stdout' => 'Not added yet', + // 'stderr' => \mb_substr($stderr, -4000), // log last 4000 chars output + 'stderr' => 'Not added yet', 'time' => $executionTime, ])); From 28dece1adfc5b43ed759c2d329eb3a2ab9c5b7f5 Mon Sep 17 00:00:00 2001 From: kodumbeats Date: Wed, 31 Mar 2021 15:41:35 -0400 Subject: [PATCH 5/6] Investigate latency of exec --- app/workers/functions.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/app/workers/functions.php b/app/workers/functions.php index 68b62c8cb..c1f76b9d0 100644 --- a/app/workers/functions.php +++ b/app/workers/functions.php @@ -472,6 +472,7 @@ class FunctionsV1 ); $body = json_encode($body); + $createExecStart = microtime(true); \curl_setopt($ch, CURLOPT_POSTFIELDS, $body); $headers = [ @@ -491,11 +492,14 @@ class FunctionsV1 \curl_close($ch); + $createExecTime = microtime(true)- $createExecStart; + var_dump($createExecTime); /* * Start execution without detatching - will receive stdout/stderr as response */ + $startExecStart = microtime(true); $ch = \curl_init(); $URL = "http://localhost/exec/{$execId}/start"; \curl_setopt($ch, CURLOPT_URL, $URL); @@ -513,11 +517,14 @@ class FunctionsV1 $result = \curl_exec($ch); var_dump($result); + if (\curl_errno($ch)) { echo 'Error:' . \curl_error($ch); } \curl_close($ch); + $startExecTime = microtime(true)- $startExecStart; + var_dump($startExecTime); sleep(1); From de47622d03e2cbac8e191e252cf61899be1b4f67 Mon Sep 17 00:00:00 2001 From: kodumbeats Date: Thu, 1 Apr 2021 09:31:30 -0400 Subject: [PATCH 6/6] Remove sleep and pass expected vars to logs --- app/workers/functions.php | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/app/workers/functions.php b/app/workers/functions.php index c1f76b9d0..2a53720ca 100644 --- a/app/workers/functions.php +++ b/app/workers/functions.php @@ -514,9 +514,8 @@ class FunctionsV1 ]; \curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); - $result = \curl_exec($ch); - var_dump($result); - + $startData = \curl_exec($ch); + var_dump($startData); if (\curl_errno($ch)) { echo 'Error:' . \curl_error($ch); @@ -526,8 +525,6 @@ class FunctionsV1 $startExecTime = microtime(true)- $startExecStart; var_dump($startExecTime); - sleep(1); - // TODO@kodumbeats: set up listener for /events for exec_start and exec_die // We need this to get accurate // $params = [ @@ -564,7 +561,6 @@ class FunctionsV1 \curl_close($ch); - // $exitCode = Console::execute("docker exec ".\implode(" ", $vars)." {$container} {$command}" // , '', $stdout, $stderr, $function->getAttribute('timeout', (int) App::getEnv('_APP_FUNCTIONS_TIMEOUT', 900))); @@ -572,7 +568,7 @@ class FunctionsV1 $executionTime = ($executionEnd - $executionStart); $functionStatus = ($exitCode === 0) ? 'completed' : 'failed'; - Console::info("Function executed in " . ($executionEnd - $executionStart) . " seconds with exit code {$exitCode}"); + Console::info("Function executed in " . ($startExecTime) . " seconds with exit code {$exitCode}"); Authorization::disable(); @@ -581,10 +577,10 @@ class FunctionsV1 'status' => $functionStatus, 'exitCode' => $exitCode, // 'stdout' => \mb_substr($stdout, -4000), // log last 4000 chars output - 'stdout' => 'Not added yet', + 'stdout' => ($exitCode === 0) ? \mb_substr($startData, -4000) : '', // 'stderr' => \mb_substr($stderr, -4000), // log last 4000 chars output - 'stderr' => 'Not added yet', - 'time' => $executionTime, + 'stderr' => (!$exitCode === 0) ? \mb_substr($startData, -4000) : '', + 'time' => $startExecTime, ])); Authorization::reset();