diff --git a/src/Orchestration/Adapter.php b/src/Orchestration/Adapter.php index 81c957a..34326ec 100644 --- a/src/Orchestration/Adapter.php +++ b/src/Orchestration/Adapter.php @@ -62,10 +62,11 @@ abstract public function listNetworks(): array; /** * Get usage stats of containers * + * @param string $container * @param array $filters * @return array<\Utopia\Orchestration\Container\Stats> */ - abstract public function getStats(?string $container = null, array $filters = []): array; + abstract public function getStats(string $container = null, array $filters = []): array; /** * Pull Image diff --git a/src/Orchestration/Adapter/DockerAPI.php b/src/Orchestration/Adapter/DockerAPI.php index e12a063..f99133c 100644 --- a/src/Orchestration/Adapter/DockerAPI.php +++ b/src/Orchestration/Adapter/DockerAPI.php @@ -22,7 +22,7 @@ public function __construct(?string $username = null, ?string $password = null, $this->registryAuth = base64_encode(json_encode([ 'username' => $username, 'password' => $password, - 'serveraddress' => 'https://index.docker.io/v1/', + 'serveraddress' => 'index.docker.io/v1/', 'email' => $email, ])); } @@ -44,6 +44,7 @@ public function __construct(?string $username = null, ?string $password = null, */ protected function call(string $url, string $method, $body = null, array $headers = [], int $timeout = -1): array { + $headers[] = 'Host: utopia-php'; // Fix Swoole headers bug with socket requests $ch = \curl_init(); \curl_setopt($ch, CURLOPT_URL, $url); \curl_setopt($ch, CURLOPT_UNIX_SOCKET_PATH, '/var/run/docker.sock'); @@ -94,11 +95,15 @@ protected function call(string $url, string $method, $body = null, array $header */ protected function streamCall(string $url, int $timeout = -1): array { + $body = \json_encode([ + 'Detach' => false, + ]); + $ch = \curl_init(); \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, '{}'); // body is required + \curl_setopt($ch, CURLOPT_POSTFIELDS, $body); // body is required \curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); $headers = [ @@ -128,7 +133,11 @@ protected function streamCall(string $url, int $timeout = -1): array $stdout = ''; $stderr = ''; - $callback = function (CurlHandle $ch, string $str) use (&$stdout, &$stderr): int { + $callback = function (mixed $ch, string $str) use (&$stdout, &$stderr): int { + if (empty($str)) { + return 0; + } + $rawStream = unpack('C*', $str); $stream = $rawStream[1]; // 1-based index, not 0-based switch ($stream) { // only 1 or 2, as set while creating exec diff --git a/src/Orchestration/Adapter/DockerCLI.php b/src/Orchestration/Adapter/DockerCLI.php index cd57630..002753a 100644 --- a/src/Orchestration/Adapter/DockerCLI.php +++ b/src/Orchestration/Adapter/DockerCLI.php @@ -15,9 +15,11 @@ class DockerCLI extends Adapter /** * Constructor * + * @param string $username + * @param string $password * @return void */ - public function __construct(?string $username = null, ?string $password = null) + public function __construct(string $username = null, string $password = null) { if ($username && $password) { $output = ''; @@ -79,10 +81,11 @@ public function networkDisconnect(string $container, string $network, bool $forc /** * Get usage stats of containers * + * @param string $container * @param array $filters * @return array */ - public function getStats(?string $container = null, array $filters = []): array + public function getStats(string $container = null, array $filters = []): array { // List ahead of time, since docker stats does not allow filtering $containerIds = []; @@ -147,17 +150,18 @@ public function getStats(?string $container = null, array $filters = []): array */ private function parseIOStats(string $stats) { + $stats = \strtolower($stats); $units = [ - 'B' => 1, - 'KB' => 1000, - 'MB' => 1000000, - 'GB' => 1000000000, - 'TB' => 1000000000000, - - 'KiB' => 1000, - 'MiB' => 1000000, - 'GiB' => 1000000000, - 'TiB' => 1000000000000, + 'b' => 1, + 'kb' => 1000, + 'mb' => 1000000, + 'gb' => 1000000000, + 'tb' => 1000000000000, + + 'kib' => 1000, + 'mib' => 1000000, + 'gib' => 1000000000, + 'tib' => 1000000000000, ]; [$inStr, $outStr] = \explode(' / ', $stats); @@ -168,7 +172,8 @@ private function parseIOStats(string $stats) foreach ($units as $unit => $value) { if (\str_ends_with($inStr, $unit)) { $inUnit = $unit; - } elseif (\str_ends_with($outStr, $unit)) { + } + if (\str_ends_with($outStr, $unit)) { $outUnit = $unit; } } diff --git a/src/Orchestration/Orchestration.php b/src/Orchestration/Orchestration.php index c6dcd4c..f12acf2 100644 --- a/src/Orchestration/Orchestration.php +++ b/src/Orchestration/Orchestration.php @@ -110,10 +110,11 @@ public function networkConnect(string $container, string $network): bool /** * Get usage stats of containers * + * @param string $container * @param array $filters * @return array<\Utopia\Orchestration\Container\Stats> */ - public function getStats(?string $container = null, array $filters = []): array + public function getStats(string $container = null, array $filters = []): array { return $this->adapter->getStats($container, $filters); } diff --git a/tests/Orchestration/Base.php b/tests/Orchestration/Base.php index 8679f6c..5809436 100644 --- a/tests/Orchestration/Base.php +++ b/tests/Orchestration/Base.php @@ -547,8 +547,8 @@ public function testUsageStats(): void $this->assertEquals($stats[0]->getContainerId(), $stats2[0]->getContainerId()); $this->assertEquals($stats[0]->getContainerName(), $stats2[0]->getContainerName()); - $this->assertGreaterThanOrEqual(0.5, $stats[0]->getCpuUsage()); - $this->assertGreaterThanOrEqual(0.5, $stats[1]->getCpuUsage()); + $this->assertGreaterThanOrEqual(0, $stats[0]->getCpuUsage()); + $this->assertGreaterThanOrEqual(0, $stats[1]->getCpuUsage()); $statsFiltered = static::getOrchestration()->getStats(filters: ['label' => 'utopia-container-type=stats']); $this->assertCount(1, $statsFiltered);