From f8f6f6ecf49784005cad0a624cbf6ce2db22bc89 Mon Sep 17 00:00:00 2001 From: Jakub Bednar Date: Wed, 13 Oct 2021 12:45:24 +0200 Subject: [PATCH 1/3] feat: add a ping() API to check status of OSS and Cloud instance --- README.md | 2 +- src/InfluxDB2/Client.php | 14 + src/InfluxDB2/Service/PingService.php | 518 ++++++++++++++++++++++++++ tests/ClientTest.php | 23 ++ 4 files changed, 556 insertions(+), 1 deletion(-) create mode 100644 src/InfluxDB2/Service/PingService.php diff --git a/README.md b/README.md index b8a297fc..e1c9ad8a 100644 --- a/README.md +++ b/README.md @@ -328,7 +328,7 @@ $this->writeApi->write($point); ### Check the server status -Server availability can be checked using the `$client->health();` method. That is equivalent of the [influx ping](https://v2.docs.influxdata.com/v2.0/reference/cli/influx/ping/). +Server availability can be checked using the `$client->ping();` method. That is equivalent of the [influx ping](https://v2.docs.influxdata.com/v2.0/reference/cli/influx/ping/). ### InfluxDB 1.8 API compatibility diff --git a/src/InfluxDB2/Client.php b/src/InfluxDB2/Client.php index 2ef6b6c1..ba04be53 100644 --- a/src/InfluxDB2/Client.php +++ b/src/InfluxDB2/Client.php @@ -3,6 +3,7 @@ namespace InfluxDB2; use InfluxDB2\Model\HealthCheck; +use InfluxDB2\Service\PingService; use ReflectionClass; use RuntimeException; @@ -101,6 +102,7 @@ public function createQueryApi(): QueryApi /** * Get the health of an instance. * + * @deprecated Use `ping()` instead * @return HealthCheck */ public function health(): HealthCheck @@ -108,6 +110,18 @@ public function health(): HealthCheck return (new HealthApi($this->options))->health(); } + /** + * Checks the status of InfluxDB instance and version of InfluxDB. + * + * @return array with response headers: 'X-Influxdb-Build', 'X-Influxdb-Version' + */ + public function ping(): array + { + $service = $this->createService(PingService::class); + $pingWithHttpInfo = $service->getPingWithHttpInfo(); + return $pingWithHttpInfo[2]; + } + /** * Close all connections into InfluxDB */ diff --git a/src/InfluxDB2/Service/PingService.php b/src/InfluxDB2/Service/PingService.php new file mode 100644 index 00000000..607a67c3 --- /dev/null +++ b/src/InfluxDB2/Service/PingService.php @@ -0,0 +1,518 @@ +client = $client ?: new Client(); + $this->config = $config ?: new Configuration(); + $this->headerSelector = $selector ?: new HeaderSelector(); + } + + /** + * @return Configuration + */ + public function getConfig() + { + return $this->config; + } + + /** + * Operation getPing + * + * Checks the status of InfluxDB instance and version of InfluxDB. + * + * + * @throws \InfluxDB2\ApiException on non-2xx response + * @throws \InvalidArgumentException + * @return void + */ + public function getPing() + { + $this->getPingWithHttpInfo(); + } + + /** + * Operation getPingWithHttpInfo + * + * Checks the status of InfluxDB instance and version of InfluxDB. + * + * + * @throws \InfluxDB2\ApiException on non-2xx response + * @throws \InvalidArgumentException + * @return array of null, HTTP status code, HTTP response headers (array of strings) + */ + public function getPingWithHttpInfo() + { + $request = $this->getPingRequest(); + + try { + $options = $this->createHttpClientOption(); + try { + $response = $this->client->send($request, $options); + } catch (RequestException $e) { + throw new ApiException( + "[{$e->getCode()}] {$e->getMessage()}", + $e->getCode(), + $e->getResponse() ? $e->getResponse()->getHeaders() : null, + $e->getResponse() ? $e->getResponse()->getBody()->getContents() : null + ); + } + + $statusCode = $response->getStatusCode(); + + if ($statusCode < 200 || $statusCode > 299) { + throw new ApiException( + sprintf( + '[%d] Error connecting to the API (%s)', + $statusCode, + $request->getUri() + ), + $statusCode, + $response->getHeaders(), + $response->getBody() + ); + } + + return [null, $statusCode, $response->getHeaders()]; + + } catch (ApiException $e) { + switch ($e->getCode()) { + } + throw $e; + } + } + + /** + * Operation getPingAsync + * + * Checks the status of InfluxDB instance and version of InfluxDB. + * + * + * @throws \InvalidArgumentException + * @return \GuzzleHttp\Promise\PromiseInterface + */ + public function getPingAsync() + { + return $this->getPingAsyncWithHttpInfo() + ->then( + function ($response) { + return $response[0]; + } + ); + } + + /** + * Operation getPingAsyncWithHttpInfo + * + * Checks the status of InfluxDB instance and version of InfluxDB. + * + * + * @throws \InvalidArgumentException + * @return \GuzzleHttp\Promise\PromiseInterface + */ + public function getPingAsyncWithHttpInfo() + { + $returnType = ''; + $request = $this->getPingRequest(); + + return $this->client + ->sendAsync($request, $this->createHttpClientOption()) + ->then( + function ($response) use ($returnType) { + return [null, $response->getStatusCode(), $response->getHeaders()]; + }, + function ($exception) { + $response = $exception->getResponse(); + $statusCode = $response->getStatusCode(); + throw new ApiException( + sprintf( + '[%d] Error connecting to the API (%s)', + $statusCode, + $exception->getRequest()->getUri() + ), + $statusCode, + $response->getHeaders(), + $response->getBody() + ); + } + ); + } + + /** + * Create request for operation 'getPing' + * + * + * @throws \InvalidArgumentException + * @return \GuzzleHttp\Psr7\Request + */ + protected function getPingRequest() + { + + $resourcePath = '/ping'; + $formParams = []; + $queryParams = []; + $headerParams = []; + $httpBody = ''; + $multipart = false; + + + + // body params + $_tempBody = null; + + if ($multipart) { + $headers = $this->headerSelector->selectHeadersForMultipart( + [] + ); + } else { + $headers = $this->headerSelector->selectHeaders( + [], + [] + ); + } + + // for model (json/xml) + if (isset($_tempBody)) { + // $_tempBody is the method argument, if present + if ($headers['Content-Type'] === 'application/json') { + $httpBody = \GuzzleHttp\json_encode(ObjectSerializer::sanitizeForSerialization($_tempBody)); + } else { + $httpBody = $_tempBody; + } + } elseif (count($formParams) > 0) { + if ($multipart) { + $multipartContents = []; + foreach ($formParams as $formParamName => $formParamValue) { + $multipartContents[] = [ + 'name' => $formParamName, + 'contents' => $formParamValue + ]; + } + // for HTTP post (form) + $httpBody = new MultipartStream($multipartContents); + + } elseif ($headers['Content-Type'] === 'application/json') { + $httpBody = \GuzzleHttp\json_encode($formParams); + + } else { + // for HTTP post (form) + $httpBody = \GuzzleHttp\Psr7\build_query($formParams); + } + } + + + $defaultHeaders = []; + if ($this->config->getUserAgent()) { + $defaultHeaders['User-Agent'] = $this->config->getUserAgent(); + } + + $headers = array_merge( + $defaultHeaders, + $headerParams, + $headers + ); + + $query = \GuzzleHttp\Psr7\build_query($queryParams); + return new Request( + 'GET', + $this->config->getHost() . $resourcePath . ($query ? "?{$query}" : ''), + $headers, + $httpBody + ); + } + + /** + * Operation headPing + * + * Checks the status of InfluxDB instance and version of InfluxDB. + * + * + * @throws \InfluxDB2\ApiException on non-2xx response + * @throws \InvalidArgumentException + * @return void + */ + public function headPing() + { + $this->headPingWithHttpInfo(); + } + + /** + * Operation headPingWithHttpInfo + * + * Checks the status of InfluxDB instance and version of InfluxDB. + * + * + * @throws \InfluxDB2\ApiException on non-2xx response + * @throws \InvalidArgumentException + * @return array of null, HTTP status code, HTTP response headers (array of strings) + */ + public function headPingWithHttpInfo() + { + $request = $this->headPingRequest(); + + try { + $options = $this->createHttpClientOption(); + try { + $response = $this->client->send($request, $options); + } catch (RequestException $e) { + throw new ApiException( + "[{$e->getCode()}] {$e->getMessage()}", + $e->getCode(), + $e->getResponse() ? $e->getResponse()->getHeaders() : null, + $e->getResponse() ? $e->getResponse()->getBody()->getContents() : null + ); + } + + $statusCode = $response->getStatusCode(); + + if ($statusCode < 200 || $statusCode > 299) { + throw new ApiException( + sprintf( + '[%d] Error connecting to the API (%s)', + $statusCode, + $request->getUri() + ), + $statusCode, + $response->getHeaders(), + $response->getBody() + ); + } + + return [null, $statusCode, $response->getHeaders()]; + + } catch (ApiException $e) { + switch ($e->getCode()) { + } + throw $e; + } + } + + /** + * Operation headPingAsync + * + * Checks the status of InfluxDB instance and version of InfluxDB. + * + * + * @throws \InvalidArgumentException + * @return \GuzzleHttp\Promise\PromiseInterface + */ + public function headPingAsync() + { + return $this->headPingAsyncWithHttpInfo() + ->then( + function ($response) { + return $response[0]; + } + ); + } + + /** + * Operation headPingAsyncWithHttpInfo + * + * Checks the status of InfluxDB instance and version of InfluxDB. + * + * + * @throws \InvalidArgumentException + * @return \GuzzleHttp\Promise\PromiseInterface + */ + public function headPingAsyncWithHttpInfo() + { + $returnType = ''; + $request = $this->headPingRequest(); + + return $this->client + ->sendAsync($request, $this->createHttpClientOption()) + ->then( + function ($response) use ($returnType) { + return [null, $response->getStatusCode(), $response->getHeaders()]; + }, + function ($exception) { + $response = $exception->getResponse(); + $statusCode = $response->getStatusCode(); + throw new ApiException( + sprintf( + '[%d] Error connecting to the API (%s)', + $statusCode, + $exception->getRequest()->getUri() + ), + $statusCode, + $response->getHeaders(), + $response->getBody() + ); + } + ); + } + + /** + * Create request for operation 'headPing' + * + * + * @throws \InvalidArgumentException + * @return \GuzzleHttp\Psr7\Request + */ + protected function headPingRequest() + { + + $resourcePath = '/ping'; + $formParams = []; + $queryParams = []; + $headerParams = []; + $httpBody = ''; + $multipart = false; + + + + // body params + $_tempBody = null; + + if ($multipart) { + $headers = $this->headerSelector->selectHeadersForMultipart( + [] + ); + } else { + $headers = $this->headerSelector->selectHeaders( + [], + [] + ); + } + + // for model (json/xml) + if (isset($_tempBody)) { + // $_tempBody is the method argument, if present + if ($headers['Content-Type'] === 'application/json') { + $httpBody = \GuzzleHttp\json_encode(ObjectSerializer::sanitizeForSerialization($_tempBody)); + } else { + $httpBody = $_tempBody; + } + } elseif (count($formParams) > 0) { + if ($multipart) { + $multipartContents = []; + foreach ($formParams as $formParamName => $formParamValue) { + $multipartContents[] = [ + 'name' => $formParamName, + 'contents' => $formParamValue + ]; + } + // for HTTP post (form) + $httpBody = new MultipartStream($multipartContents); + + } elseif ($headers['Content-Type'] === 'application/json') { + $httpBody = \GuzzleHttp\json_encode($formParams); + + } else { + // for HTTP post (form) + $httpBody = \GuzzleHttp\Psr7\build_query($formParams); + } + } + + + $defaultHeaders = []; + if ($this->config->getUserAgent()) { + $defaultHeaders['User-Agent'] = $this->config->getUserAgent(); + } + + $headers = array_merge( + $defaultHeaders, + $headerParams, + $headers + ); + + $query = \GuzzleHttp\Psr7\build_query($queryParams); + return new Request( + 'HEAD', + $this->config->getHost() . $resourcePath . ($query ? "?{$query}" : ''), + $headers, + $httpBody + ); + } + + /** + * Create http client option + * + * @throws \RuntimeException on file opening failure + * @return array of http client options + */ + protected function createHttpClientOption() + { + $options = []; + if ($this->config->getDebug()) { + $options[RequestOptions::DEBUG] = fopen($this->config->getDebugFile(), 'a'); + if (!$options[RequestOptions::DEBUG]) { + throw new \RuntimeException('Failed to open the debug file: ' . $this->config->getDebugFile()); + } + } + + return $options; + } +} diff --git a/tests/ClientTest.php b/tests/ClientTest.php index f1b0863b..ec9fa36d 100644 --- a/tests/ClientTest.php +++ b/tests/ClientTest.php @@ -2,6 +2,7 @@ namespace InfluxDB2Test; +use GuzzleHttp\Exception\ConnectException; use InfluxDB2\Client; require_once('BasicTest.php'); @@ -34,4 +35,26 @@ public function test_health_not_running() $this->assertEquals('influxdb', $health->getName()); $this->assertEquals('fail', $health->getStatus()); } + + public function test_ping() + { + $ping = $this->client->ping(); + + $this->assertArrayHasKey('X-Influxdb-Build', $ping); + $this->assertArrayHasKey('X-Influxdb-Version', $ping); + } + + public function test_ping_not_running() + { + $this->client->close(); + $this->client = new Client([ + "url" => "http://localhost:8099", + "token" => "my-token", + ]); + + $this->expectException(ConnectException::class); + $this->expectExceptionMessage("Failed to connect to localhost"); + + $this->client->ping(); + } } From 21f66da52deedbd2d7648f3ceef738592c39876e Mon Sep 17 00:00:00 2001 From: Jakub Bednar Date: Wed, 13 Oct 2021 12:49:37 +0200 Subject: [PATCH 2/3] feat: add a ping() API to check status of OSS and Cloud instance --- tests/ClientTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/ClientTest.php b/tests/ClientTest.php index ec9fa36d..1a888d7d 100644 --- a/tests/ClientTest.php +++ b/tests/ClientTest.php @@ -2,7 +2,7 @@ namespace InfluxDB2Test; -use GuzzleHttp\Exception\ConnectException; +use Exception; use InfluxDB2\Client; require_once('BasicTest.php'); @@ -52,7 +52,7 @@ public function test_ping_not_running() "token" => "my-token", ]); - $this->expectException(ConnectException::class); + $this->expectException(Exception::class); $this->expectExceptionMessage("Failed to connect to localhost"); $this->client->ping(); From 6e5ef37e4ef05f52ecb051abda90ed9db3c8f33a Mon Sep 17 00:00:00 2001 From: Jakub Bednar Date: Wed, 13 Oct 2021 12:50:47 +0200 Subject: [PATCH 3/3] docs: update CHANGELOG.md --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 33b1e927..dd249ecb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ ## 2.3.0 [unreleased] +### Features +1. [#97](https://github.com/influxdata/influxdb-client-php/pull/97): Add `ping()` to check status of OSS and Cloud instance + ### Bug Fixes 1. [#95](https://github.com/influxdata/influxdb-client-php/pull/95): Fix file descriptor leaks in WriteApi 1. [#96](https://github.com/influxdata/influxdb-client-php/pull/96): Fix nanosecond datetime string convertor