diff --git a/specs/HiveMQ-4.4.0-OpenAPI-spec.yaml b/specs/HiveMQ-4.4.0-OpenAPI-spec.yaml index 5587d28fe..486f1b95b 100644 --- a/specs/HiveMQ-4.4.0-OpenAPI-spec.yaml +++ b/specs/HiveMQ-4.4.0-OpenAPI-spec.yaml @@ -11,12 +11,14 @@ info: - Listing all subscriptions for a specific MQTT client - Getting the connection status for a specific MQTT client - Creating and restoring a backup + - Starting and stopping a trace recording + - Downloading backups and trace recordings ## API style HiveMQ's API is organized in a [RESTful](http://en.wikipedia.org/wiki/Representational_State_Transfer) fashion. The API has predictable resource-oriented URLs that consume and return JSON with the content-type `application/json`. - It uses standard HTTP response codes and verbs. Some endpoints do return files, those are using the content type `application/octet-stream`. + It uses standard HTTP response codes and verbs. Some endpoints do return files, those are using the content type `application/octet-stream` or `application/zip`. The base URL is the Host and configured port of your HiveMQ instances. In most cases it makes sense to configure a reverse-proxy or load balancer to access HiveMQ's REST API. @@ -76,37 +78,47 @@ info: HiveMQ's REST API provides an OpenAPI 3.0 schema definition that can imported into popular API tooling (e.g. Postman) or can be used to generate client-code for multiple programming languages. contact: url: https://www.hivemq.com - version: 4.4.0-SNAPSHOT + version: 4.4.0 x-logo: url: https://www.hivemq.com/img/svg/hivemq-bee.svg tags: - - name: Backup & Restore - description: |- - These endpoints can be used to create, download, inspect and restore backups created by HiveMQ. +- name: Backup & Restore + description: |- + These endpoints can be used to create, download, inspect and restore backups created by HiveMQ. - More information about the backup and restore capabilities of HiveMQ can be found in the [HiveMQ documentation](https://www.hivemq.com/docs/hivemq/latest/user-guide/backup-restore.html). + More information about the backup and restore capabilities of HiveMQ can be found in the [HiveMQ documentation](https://www.hivemq.com/docs/hivemq/latest/user-guide/backup-restore.html). - ### Backup Requirements - Some prerequisites are necessary to create a backup or restore from a backup: + ### Backup Requirements + Some prerequisites are necessary to create a backup or restore from a backup: - - All HiveMQ nodes have at least version 4.4.0 - - Only one backup/restore can be executed at the same time + - All HiveMQ nodes have at least version 4.4.0 + - Only one backup/restore can be executed at the same time - ### Export Requirements - The following requirements are necessary to successfully create a backup: + ### Export Requirements + The following requirements are necessary to successfully create a backup: - - All HiveMQ nodes have at least 1GB of free disk space - - No cluster topology changes occur during the export. The backup is aborted when the topology changes to avoid inconsistent data in the backup. + - All HiveMQ nodes have at least 1GB of free disk space + - No cluster topology changes occur during the export. The backup is aborted when the topology changes to avoid inconsistent data in the backup. - ### Restore Requirements + ### Restore Requirements - The requirements to successfully restore data from a backup are: + The requirements to successfully restore data from a backup are: - - A clean HiveMQ deployment. This means that no clients must be connected and no persistent data exists on every HiveMQ node. The import will not start if there is data available in your cluster. - - Message data used by Extensions are only restored if the corresponding extension is already started before the restore is started. - - name: MQTT Clients - description: "These endpoints can be used to inspect the MQTT clients that are known\ + - A clean HiveMQ deployment. This means that no clients must be connected and no persistent data exists on every HiveMQ node. The import will not start if there is data available in your cluster. + - Message data used by Extensions are only restored if the corresponding extension is already started before the restore is started. +- name: Trace Recordings + description: | + A Trace Recording is a combination of filters which allows you to select messages of specific clients or topics, which are logged to a file in a human readable format. + Each trace recording creates cluster-wide trace files that can be downloaded as a collective zip file. + + You can log any MQTT message sent or received by the broker with a filter you apply. A Filter can either be a client identifier or a topic. Many filter combinations are possible. All filters are regular expressions. + + These endpoints can be used to create, download, inspect, stop and delete trace recordings. + + More information about the trace recording capabilities of HiveMQ can be found in the [HiveMQ documentation](https://www.hivemq.com/docs/hivemq/latest/control-center/analytic.html#trace-recording). +- name: MQTT Clients + description: "These endpoints can be used to inspect the MQTT clients that are known\ \ to HiveMQ.\n\nWith millions of connected clients, keeping track of specific\ \ clients can become a challenge. The HiveMQ REST API provides endpoints to list\ \ and view all the MQTT clients known to HiveMQ. \nInformation about subscriptions,\ @@ -115,21 +127,21 @@ paths: /api/v1/management/files/backups/{backupId}: get: tags: - - Backup & Restore + - Backup & Restore summary: Download a backup file description: "Download a specific backup file. \n\n This endpoint returns the\ \ content of the backup file with the content-type `application/octet-stream`.\ \ \n\n Only backups in the states `COMPLETED`, `RESTORE_IN_PROGRESS`, `RESTORE_FAILED`\ \ or `RESTORE_COMPLETED` can be downloaded.\n\n This endpoint requires at\ \ least HiveMQ version 4.4.0. on all cluster nodes." - operationId: management.files.backups.backupId.get + operationId: downloadBackupFile parameters: - - name: backupId - in: path - description: The id of the backup. - required: true - schema: - type: string + - name: backupId + in: path + description: The id of the backup. + required: true + schema: + type: string responses: "200": description: Success @@ -155,8 +167,8 @@ paths: description: Resource not found value: errors: - - title: Resource not found - detail: Resource with id 'my-resource-id' not found + - title: Resource not found + detail: Resource with id 'my-resource-id' not found "400": description: Bad request content: @@ -169,8 +181,8 @@ paths: description: Bad request value: errors: - - title: Required parameter missing - detail: Required URL parameter 'parameterName' is missing + - title: Required parameter missing + detail: Required URL parameter 'parameterName' is missing "503": description: Cluster node not reachable during download content: @@ -183,13 +195,169 @@ paths: description: The endpoint is temporarily not available value: errors: - - title: The endpoint is temporarily not available - detail: The endpoint is temporarily not available, please try - again later + - title: The endpoint is temporarily not available + detail: The endpoint is temporarily not available, please try + again later + /api/v1/management/backups/{backupId}: + get: + tags: + - Backup & Restore + summary: Get backup information + description: |- + Returns the information for a specific backup with its current state. + + This endpoint can be used to check the progress of a specific backup when it is being created or being restored. + + Canceled or failed backups are returned for up to 1 hour after the have been requested. + + This endpoint requires at least HiveMQ version 4.4.0. on all cluster nodes. + operationId: getBackup + parameters: + - name: backupId + in: path + description: The id of the backup. + required: true + schema: + type: string + responses: + "200": + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/BackupItem' + examples: + get-example: + summary: Example with a completed backup + description: Example response. + value: + backup: + id: 20200506-081317 + createdAt: 2020-05-06T08:13:17Z + bytes: 85550653 + state: COMPLETED + "404": + description: Resource not found + content: + application/json: + schema: + $ref: '#/components/schemas/Errors' + examples: + not-found: + summary: Not found + description: Not found + value: + errors: + - title: Resource not found + detail: Resource with id 'my-resource-id' not found + "400": + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Errors' + examples: + param-missing: + summary: Required URL parameter missing + description: Bad request + value: + errors: + - title: Required parameter missing + detail: Required URL parameter 'parameterName' is missing + "503": + description: Not all cluster nodes at minimum version + content: + application/json: + schema: + $ref: '#/components/schemas/Errors' + examples: + version-check-failed: + summary: Version check failed + description: Version check failed + value: + errors: + - title: Endpoint not active yet + detail: Not all cluster nodes support this endpoint yet, please + try again later + post: + tags: + - Backup & Restore + summary: Restore a new backup + description: |- + Triggers the restore of a stored backup. + + This endpoint requires at least HiveMQ version 4.4.0. on all cluster nodes. + operationId: restoreBackup + parameters: + - name: backupId + in: path + description: The id of the backup. + required: true + schema: + type: string + responses: + "200": + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/BackupItem' + examples: + example: + summary: Created backup that is currently in progress + description: Example response. + value: + backup: + id: 20201006-1902318 + createdAt: 2020-05-06T08:13:17Z + state: IN_PROGRESS + "404": + description: Resource not found + content: + application/json: + schema: + $ref: '#/components/schemas/Errors' + examples: + not-found: + summary: Not found + description: Example not found + value: + errors: + - title: Resource not found + detail: Resource with id 'my-resource-id' not found + "400": + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Errors' + examples: + param-missing: + summary: Required URL parameter missing + description: Bad request + value: + errors: + - title: Required parameter missing + detail: Required URL parameter 'parameterName' is missing + "503": + description: Not all cluster nodes at minimum version + content: + application/json: + schema: + $ref: '#/components/schemas/Errors' + examples: + version-check-failed: + summary: Version check failed + description: Version check failed + value: + errors: + - title: Endpoint not active yet + detail: Not all cluster nodes support this endpoint yet, please + try again later /api/v1/management/backups: get: tags: - - Backup & Restore + - Backup & Restore summary: List all available backups description: |- Lists all available backups with their current state. @@ -199,7 +367,7 @@ paths: Canceled or failed backups are included in the results for up to 1 hour after they have been requested. This endpoint requires at least HiveMQ version 4.4.0. on all cluster nodes. - operationId: management.backups.get + operationId: getAllBackups responses: "200": description: Success @@ -214,17 +382,17 @@ paths: that is currently in progress. value: items: - - id: 20200506-081317 - createdAt: 2020-05-06T08:13:17Z - bytes: 85550653 - state: COMPLETED - - id: 20201006-1902318 - createdAt: 2020-05-06T08:13:17Z - state: IN_PROGRESS - - id: 20201006-1902318 - createdAt: 2020-05-06T08:13:17Z - state: FAILED - failReason: Another backup is already in progress. + - id: 20200506-081317 + createdAt: 2020-05-06T08:13:17Z + bytes: 85550653 + state: COMPLETED + - id: 20201006-1902318 + createdAt: 2020-05-06T08:13:17Z + state: IN_PROGRESS + - id: 20201006-1902318 + createdAt: 2020-05-06T08:13:17Z + state: FAILED + failReason: Another backup is already in progress. empty-results: summary: Empty result if no backups are known description: Empty result if no backups are known. @@ -242,18 +410,18 @@ paths: description: Version check failed value: errors: - - title: Endpoint not active yet - detail: Not all cluster nodes support this endpoint yet, please - try again later + - title: Endpoint not active yet + detail: Not all cluster nodes support this endpoint yet, please + try again later post: tags: - - Backup & Restore + - Backup & Restore summary: Create a new backup description: |- Triggers the creation of a new backup. This endpoint requires at least HiveMQ version 4.4.0. on all cluster nodes. - operationId: management.backups.post + operationId: createBackup responses: "200": description: Success @@ -282,47 +450,39 @@ paths: description: Version check failed value: errors: - - title: Endpoint not active yet - detail: Not all cluster nodes support this endpoint yet, please - try again later - /api/v1/management/backups/{backupId}: + - title: Endpoint not active yet + detail: Not all cluster nodes support this endpoint yet, please + try again later + /api/v1/management/files/trace-recordings/{traceRecordingId}: get: tags: - - Backup & Restore - summary: Get backup information - description: |- - Returns the information for a specific backup with its current state. - - This endpoint can be used to check the progress of a specific backup when it is being created or being restored. - - Canceled or failed backups are returned for up to 1 hour after the have been requested. - - This endpoint requires at least HiveMQ version 4.4.0. on all cluster nodes. - operationId: management.backups.backupId.get + - Trace Recordings + summary: Download a trace recording + description: "Download a specific trace recording. \n\n This endpoint returns\ + \ the content of the trace recording with the content-type `application/zip`.\ + \ \n\nOnly trace recordings in the states `IN_PROGRESS`, `STOPPED` and `ABORTED`\ + \ can be downloaded." + operationId: downloadTraceRecordingFile parameters: - - name: backupId - in: path - description: The id of the backup. - required: true - schema: - type: string + - name: traceRecordingId + in: path + description: The id of the trace recording. + required: true + schema: + type: string responses: "200": description: Success content: - application/json: + application/zip: schema: - $ref: '#/components/schemas/BackupItem' + type: string + format: binary examples: - get-example: - summary: Example with a completed backup - description: Example response. - value: - backup: - id: 20200506-081317 - createdAt: 2020-05-06T08:13:17Z - bytes: 85550653 - state: COMPLETED + file-download: + summary: File download + description: File download + value: "404": description: Resource not found content: @@ -332,11 +492,11 @@ paths: examples: not-found: summary: Not found - description: Not found + description: Resource not found value: errors: - - title: Resource not found - detail: Resource with id 'my-resource-id' not found + - title: Resource not found + detail: Resource with id 'my-resource-id' not found "400": description: Bad request content: @@ -349,69 +509,343 @@ paths: description: Bad request value: errors: - - title: Required parameter missing - detail: Required URL parameter 'parameterName' is missing - "503": - description: Not all cluster nodes at minimum version + - title: Required parameter missing + detail: Required URL parameter 'parameterName' is missing + /api/v1/management/trace-recordings/{traceRecordingId}: + delete: + tags: + - Trace Recordings + summary: Delete a trace recording + description: "Deletes an existing trace recording. \n\n " + operationId: deleteTraceRecording + parameters: + - name: traceRecordingId + in: path + description: The name of the trace recording to delete. + required: true + schema: + type: string + responses: + "204": + description: Success, no response body + "400": + description: Bad request content: application/json: schema: $ref: '#/components/schemas/Errors' examples: - version-check-failed: - summary: Version check failed - description: Version check failed + param-missing: + summary: Required URL parameter missing + description: Bad request value: errors: - - title: Endpoint not active yet - detail: Not all cluster nodes support this endpoint yet, please - try again later - post: + - title: Required parameter missing + detail: Required URL parameter 'parameterName' is missing + "404": + description: Resource not found + content: + application/json: + schema: + $ref: '#/components/schemas/Errors' + examples: + not-found: + summary: Not found + description: Resource not found + value: + errors: + - title: Resource not found + detail: Resource with id 'my-resource-id' not found + patch: tags: - - Backup & Restore - summary: Restore a new backup + - Trace Recordings + summary: Stop a trace recording. description: |- - Triggers the restore of a stored backup. + Stops an existing trace recording. - This endpoint requires at least HiveMQ version 4.4.0. on all cluster nodes. - operationId: management.backups.backupId.post + Only the state of the trace recording can be set to `STOPPED` with this endpoint, changes to other fields are ignored. + operationId: stopTraceRecording parameters: - - name: backupId - in: path - description: The id of the backup. - required: true - schema: - type: string + - name: traceRecordingId + in: path + description: The name of the trace recording to patch/stop. + required: true + schema: + type: string + requestBody: + description: The trace recording to create + content: + application/json: + schema: + $ref: '#/components/schemas/TraceRecordingItem' + examples: + stop-query: + summary: Stop query + description: Request to stop a trace recording by defining its state + as STOPPED. + value: + traceRecording: + state: STOPPED responses: "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/BackupItem' + $ref: '#/components/schemas/TraceRecordingItem' examples: - example: - summary: Created backup that is currently in progress - description: Example response. + stop-response: + summary: Stop query - response + description: A stopped trace recording returned after a stop query + was sent. value: - backup: - id: 20201006-1902318 - createdAt: 2020-05-06T08:13:17Z - state: IN_PROGRESS + traceRecording: + name: test + startAt: 2020-07-23T12:07:30.000Z + endAt: 2020-07-23T13:07:30.000Z + clientIdFilters: + - regex: test + topicFilters: + - regex: test-topic + events: + - MQTT_MESSAGE_CONNECT + state: STOPPED + "400": + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Errors' + examples: + param-missing: + summary: Required URL parameter missing + description: Bad request + value: + errors: + - title: Required parameter missing + detail: Required URL parameter 'parameterName' is missing + body-param-missing: + summary: Required body entity parameter missing + description: Bad request + value: + errors: + - title: Required parameter missing + detail: Required body entity parameter is missing + invalid-resource: + summary: Invalid resource + description: Bad request + value: + errors: + - title: Invalid resource + detail: The fields {name, events, startAt, endAt} must be specified + at creation "404": description: Resource not found content: application/json: schema: - $ref: '#/components/schemas/Errors' + $ref: '#/components/schemas/Errors' + examples: + not-found: + summary: Not found + description: Resource not found + value: + errors: + - title: Resource not found + detail: Resource with id 'my-resource-id' not found + /api/v1/management/trace-recordings: + get: + tags: + - Trace Recordings + summary: Get all trace recordings + description: "Lists all known trace recordings. \n\nTrace recordings can be\ + \ in different states. These states are:\n- `SCHEDULED` if the start date\ + \ for a trace recording is in the future\n- `STOPPED` if a trace recording\ + \ has reached its end date or was stopped manually\n- `IN_PROGRESS` when the\ + \ trace recording is currently ongoing\n- `ABORTED` if the trace recording\ + \ was aborted by the server\n" + operationId: getAllTraceRecordings + responses: + "200": + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/TraceRecordingList' + examples: + single-result: + summary: Single result + description: Example response with one recording that is in progress. + value: + items: + - name: test + startAt: 2020-07-23T12:07:30.000Z + endAt: 2020-07-23T13:07:30.000Z + clientIdFilters: + - regex: client-[0-9] + topicFilters: + - regex: topic/.* + events: + - MQTT_MESSAGE_CONNECT + - MQTT_MESSAGE_DISCONNECT + state: IN_PROGRESS + post: + tags: + - Trace Recordings + summary: Create a trace recording + description: "Creates a new trace recording. \n\n To create a trace recording\ + \ you must specify a name, start date, end date, a set of filters and the\ + \ desired packets that should be traced.\n\nAt least one client or topic filter\ + \ and at least one packet is required to create a trace recording.\n\nThe\ + \ client and topic filters can be [regular expressions](https://www.hivemq.com/docs/hivemq/4.3/control-center/analytic.html#regular-expressions)." + operationId: createTraceRecording + requestBody: + description: The trace recording to create + content: + application/json: + schema: + $ref: '#/components/schemas/TraceRecordingItem' + examples: + simple-query: + summary: Simple query + description: A sample trace recording with a duration of 1 hour, tracing + one client, topic filter and CONNECT events. + value: + traceRecording: + name: test + startAt: 2020-07-23T12:07:30.000Z + endAt: 2020-07-23T13:07:30.000Z + clientIdFilters: + - regex: client-[0-9] + topicFilters: + - regex: topic/.* + events: + - MQTT_MESSAGE_CONNECT + responses: + "200": + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/TraceRecordingItem' + examples: + simple-query-result: + summary: Simple query - result + description: Response from the server after it created the trace + recording. Includes the resulting current state of the recording. + value: + traceRecording: + name: test + startAt: 2020-07-23T12:07:30.000Z + endAt: 2020-07-23T13:07:30.000Z + clientIdFilters: + - regex: test + topicFilters: + - regex: test-topic + events: + - MQTT_MESSAGE_CONNECT + state: IN_PROGRESS + "400": + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Errors' + examples: + param-missing: + summary: Required URL parameter missing + description: Bad request + value: + errors: + - title: Required parameter missing + detail: Required URL parameter 'parameterName' is missing + body-param-missing: + summary: Required body entity parameter missing + description: Bad request + value: + errors: + - title: Required parameter missing + detail: Required body entity parameter is missing + invalid-resource: + summary: Invalid resource + description: Bad request + value: + errors: + - title: Invalid resource + detail: The fields {name, events, startAt, endAt} must be specified + at creation + /api/v1/mqtt/clients: + get: + tags: + - MQTT Clients + summary: List all MQTT clients + description: |- + Lists all client sessions (online and offline) known to the whole HiveMQ cluster. + + The result contains each client's client identifier. For more details about each client you can call the endpoints that have a clientId in their URL. + + This endpoint uses pagination with a cursor. + The results are not sorted in any way, no ordering of any kind is guaranteed. + + This endpoint requires at least HiveMQ version 4.4.0. on all cluster nodes. + operationId: getAllMqttClients + parameters: + - name: limit + in: query + description: Specifies the page size for the returned results. Has to be between + 50 and 2500. Default page size is 500. + schema: + type: integer + format: int32 + - name: cursor + in: query + description: The cursor that has been returned by the previous result page. + Do not pass this parameter if you want to fetch the first page. + schema: + type: string + responses: + "200": + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/ClientList' examples: - not-found: - summary: Not found - description: Example not found + single-result: + summary: Single result + description: Example response with one known client. value: - errors: - - title: Resource not found - detail: Resource with id 'my-resource-id' not found + items: + - id: client-12 + multiple-results-last-page: + summary: Multiple results, last page + description: Example response with multiple clients. No more pages + left. + value: + items: + - id: client-12 + - id: client-5 + - id: client-32 + - id: my-client-id2 + - id: my-client-id + multiple-results-pages-left: + summary: Multiple results, more pages left + description: Example response with multiple clients. More pages + left. + value: + items: + - id: client-12 + - id: client-5 + - id: client-32 + - id: my-client-id2 + - id: my-client-id + _links: + next: /api/v1/mqtt/clients?cursor=a-MvelExpd5y0SrXBxDhBvnGmohbpzwGDQFdUyOYWBACqs1TgI4-cUo-A=&limit=5 + empty-results: + summary: Empty result if no clients are known + description: Empty result if no clients are known. + value: + items: [] "400": description: Bad request content: @@ -424,101 +858,56 @@ paths: description: Bad request value: errors: - - title: Required parameter missing - detail: Required URL parameter 'parameterName' is missing - "503": - description: Not all cluster nodes at minimum version - content: - application/json: - schema: - $ref: '#/components/schemas/Errors' - examples: - version-check-failed: - summary: Version check failed - description: Version check failed - value: - errors: - - title: Endpoint not active yet - detail: Not all cluster nodes support this endpoint yet, please - try again later - /api/v1/mqtt/clients/{clientId}/connection: - get: - tags: - - MQTT Clients - summary: Get a clients connection state - description: |- - Returns the information if a specific client is currently connected. - - If you are only interested in the connection status of a client prefer this endpoint over the the full client detail. - If your client identifiers contain special characters, please make sure that the clientId is URL Encoded (a.k.a. percent-encoding, as in RFC 3986). - operationId: mqtt.clients.clientId.get - parameters: - - name: clientId - in: path - description: The MQTT client identifier. - required: true - schema: - type: string - responses: - "200": - description: Success - content: - application/json: - schema: - $ref: '#/components/schemas/ConnectionItem' - examples: - online-client: - summary: online-client - description: Online client - value: - connection: - connected: false - "404": - description: Resource not found + - title: Required parameter missing + detail: Required URL parameter 'parameterName' is missing + "410": + description: Cursor not valid anymore content: application/json: schema: $ref: '#/components/schemas/Errors' examples: - not-found: - summary: Not found - description: Not found + cursor-invalid: + summary: The passed cursor is not valid anymore + description: Cursor not valid anymore value: errors: - - title: Resource not found - detail: Resource with id 'my-resource-id' not found - "400": - description: Bad request + - title: Cursor not valid anymore + detail: The passed cursor is not valid anymore, you can request + this resource without a cursor to start from the beginning + "503": + description: Not all cluster nodes at minimum version content: application/json: schema: $ref: '#/components/schemas/Errors' examples: - param-missing: - summary: Required URL parameter missing - description: Bad request + version-check-failed: + summary: Version check failed + description: Version check failed value: errors: - - title: Required parameter missing - detail: Required URL parameter 'parameterName' is missing + - title: Endpoint not active yet + detail: Not all cluster nodes support this endpoint yet, please + try again later /api/v1/mqtt/clients/{clientId}: get: tags: - - MQTT Clients + - MQTT Clients summary: Get detailed client information description: |- Returns detailed information for a specific client with its current state. Including all session and connection information. If your client identifiers contain special characters, please make sure that the clientId is URL Encoded (a.k.a. percent-encoding, as in RFC 3986). - operationId: mqtt.clients.clientId.get_1 + operationId: getMqttClientDetails parameters: - - name: clientId - in: path - description: The MQTT client identifier. - required: true - schema: - type: string + - name: clientId + in: path + description: The MQTT client identifier. + required: true + schema: + type: string responses: "200": description: Success @@ -587,10 +976,10 @@ paths: destinationIp: 127.0.0.3 destinationPort: 50123 tlvs: - - key: PP2_TYPE_ALPN - value: "1" - - key: PP2_TYPE_AUTHORITY - value: "2" + - key: PP2_TYPE_ALPN + value: "1" + - key: PP2_TYPE_AUTHORITY + value: "2" tlsInformation: cipherSuite: cipher_suite tlsVersion: "1.2" @@ -616,8 +1005,8 @@ paths: description: Bad request value: errors: - - title: Required parameter missing - detail: Required URL parameter 'parameterName' is missing + - title: Required parameter missing + detail: Required URL parameter 'parameterName' is missing "404": description: Resource not found content: @@ -630,141 +1019,85 @@ paths: description: Not found value: errors: - - title: Resource not found - detail: Resource with id 'my-resource-id' not found - /api/v1/mqtt/clients: + - title: Resource not found + detail: Resource with id 'my-resource-id' not found + /api/v1/mqtt/clients/{clientId}/connection: get: tags: - - MQTT Clients - summary: List all MQTT clients + - MQTT Clients + summary: Get a clients connection state description: |- - Lists all client sessions (online and offline) known to the whole HiveMQ cluster. - - The result contains each client's client identifier. For more details about each client you can call the endpoints that have a clientId in their URL. - - This endpoint uses pagination with a cursor. - The results are not sorted in any way, no ordering of any kind is guaranteed. + Returns the information if a specific client is currently connected. - This endpoint requires at least HiveMQ version 4.4.0. on all cluster nodes. - operationId: mqtt.clients.get + If you are only interested in the connection status of a client prefer this endpoint over the the full client detail. + If your client identifiers contain special characters, please make sure that the clientId is URL Encoded (a.k.a. percent-encoding, as in RFC 3986). + operationId: getMqttClientConnectionState parameters: - - name: limit - in: query - description: Specifies the page size for the returned results. Has to be between - 50 and 2500. Default page size is 500. - schema: - type: integer - format: int32 - - name: cursor - in: query - description: The cursor that has been returned by the previous result page. - Do not pass this parameter if you want to fetch the first page. - schema: - type: string + - name: clientId + in: path + description: The MQTT client identifier. + required: true + schema: + type: string responses: "200": description: Success content: application/json: schema: - $ref: '#/components/schemas/ClientList' - examples: - single-result: - summary: Single result - description: Example response with one known client. - value: - items: - - id: client-12 - multiple-results-last-page: - summary: Multiple results, last page - description: Example response with multiple clients. No more pages - left. - value: - items: - - id: client-12 - - id: client-5 - - id: client-32 - - id: my-client-id2 - - id: my-client-id - multiple-results-pages-left: - summary: Multiple results, more pages left - description: Example response with multiple clients. More pages - left. - value: - items: - - id: client-12 - - id: client-5 - - id: client-32 - - id: my-client-id2 - - id: my-client-id - _links: - next: /api/v1/mqtt/clients?cursor=a-MvelExpd5y0SrXBxDhBvnGmohbpzwGDQFdUyOYWBACqs1TgI4-cUo-A=&limit=5 - empty-results: - summary: Empty result if no clients are known - description: Empty result if no clients are known. - value: - items: [] - "400": - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/Errors' + $ref: '#/components/schemas/ConnectionItem' examples: - param-missing: - summary: Required URL parameter missing - description: Bad request + online-client: + summary: online-client + description: Online client value: - errors: - - title: Required parameter missing - detail: Required URL parameter 'parameterName' is missing - "410": - description: Cursor not valid anymore + connection: + connected: false + "404": + description: Resource not found content: application/json: schema: $ref: '#/components/schemas/Errors' examples: - cursor-invalid: - summary: The passed cursor is not valid anymore - description: Cursor not valid anymore + not-found: + summary: Not found + description: Not found value: errors: - - title: Cursor not valid anymore - detail: The passed cursor is not valid anymore, you can request - this resource without a cursor to start from the beginning - "503": - description: Not all cluster nodes at minimum version + - title: Resource not found + detail: Resource with id 'my-resource-id' not found + "400": + description: Bad request content: application/json: schema: $ref: '#/components/schemas/Errors' examples: - version-check-failed: - summary: Version check failed - description: Version check failed + param-missing: + summary: Required URL parameter missing + description: Bad request value: errors: - - title: Endpoint not active yet - detail: Not all cluster nodes support this endpoint yet, please - try again later + - title: Required parameter missing + detail: Required URL parameter 'parameterName' is missing /api/v1/mqtt/clients/{clientId}/subscriptions: get: tags: - - MQTT Clients + - MQTT Clients summary: List all subscriptions for MQTT client description: |- List all subscriptions for a specific client. This endpoint does not support pagination with cursor at the moment, but it might be added in future versions. Please make sure to check if a cursor is returned and another page is available to have a future-proof implementation. - operationId: mqtt.clients.clientId.subscriptions.get + operationId: getSubscriptionsForMqttClient parameters: - - name: clientId - in: path - description: The MQTT client identifier. - required: true - schema: - type: string + - name: clientId + in: path + description: The MQTT client identifier. + required: true + schema: + type: string responses: "200": description: Success @@ -778,24 +1111,24 @@ paths: description: Example response with multiple results. value: items: - - topicFilter: topic/0 - qos: AT_MOST_ONCE - retainHandling: SEND - retainAsPublished: true - noLocal: false - subscriptionIdentifier: 1 - - topicFilter: topic/2 - qos: EXACTLY_ONCE - retainHandling: SEND - retainAsPublished: false - noLocal: true - subscriptionIdentifier: 3 - - topicFilter: $share/sharename/topic/1 - qos: AT_LEAST_ONCE - retainHandling: DO_NOT_SEND - retainAsPublished: false - noLocal: false - subscriptionIdentifier: 2 + - topicFilter: topic/0 + qos: AT_MOST_ONCE + retainHandling: SEND + retainAsPublished: true + noLocal: false + subscriptionIdentifier: 1 + - topicFilter: topic/2 + qos: EXACTLY_ONCE + retainHandling: SEND + retainAsPublished: false + noLocal: true + subscriptionIdentifier: 3 + - topicFilter: $share/sharename/topic/1 + qos: AT_LEAST_ONCE + retainHandling: DO_NOT_SEND + retainAsPublished: false + noLocal: false + subscriptionIdentifier: 2 empty-result: summary: Empty result if client has no subscriptions description: Empty result if client has no subscriptions. @@ -813,8 +1146,8 @@ paths: description: Bad request value: errors: - - title: Required parameter missing - detail: Required URL parameter 'parameterName' is missing + - title: Required parameter missing + detail: Required URL parameter 'parameterName' is missing "404": description: Resource not found content: @@ -827,8 +1160,8 @@ paths: description: Not found value: errors: - - title: Resource not found - detail: Resource with id 'my-resource-id' not found + - title: Resource not found + detail: Resource with id 'my-resource-id' not found components: schemas: Error: @@ -861,12 +1194,12 @@ components: type: string description: The current state of the backup enum: - - COMPLETED - - RESTORE_COMPLETED - - IN_PROGRESS - - RESTORE_IN_PROGRESS - - FAILED - - RESTORE_FAILED + - COMPLETED + - RESTORE_COMPLETED + - IN_PROGRESS + - RESTORE_IN_PROGRESS + - FAILED + - RESTORE_FAILED failReason: type: string description: The reason why this backup failed, only present for failed @@ -877,6 +1210,11 @@ components: description: The size of this backup file in bytes. format: int64 nullable: true + BackupItem: + type: object + properties: + backup: + $ref: '#/components/schemas/Backup' BackupList: type: object properties: @@ -885,23 +1223,114 @@ components: description: List of result items that are returned by this endpoint items: $ref: '#/components/schemas/Backup' - BackupItem: + TraceFilter: type: object properties: - backup: - $ref: '#/components/schemas/Backup' - Connection: + regex: + type: string + description: Regex pattern this filter will trace for. + description: Topic filters to trace + TraceRecording: type: object properties: - connected: - type: boolean - description: If this client is currently connected - description: Information about the client's connection state - ConnectionItem: + name: + type: string + description: Name of the trace recording. Must be unique, contain at least + three characters and only combinations of numbers, letters, dashes and + underscores are allowed + startAt: + type: string + description: Time the trace recording is scheduled to start at + format: date-time + endAt: + type: string + description: Time the trace recording is scheduled to stop at. Must be at + a later time from the start time + format: date-time + clientIdFilters: + uniqueItems: true + type: array + description: Client ID filters to trace + items: + $ref: '#/components/schemas/TraceFilter' + topicFilters: + uniqueItems: true + type: array + description: Topic filters to trace + items: + $ref: '#/components/schemas/TraceFilter' + events: + uniqueItems: true + type: array + description: MQTT events to trace + items: + type: string + description: MQTT events to trace + enum: + - MQTT_MESSAGE_CONNECT + - MQTT_MESSAGE_CONNACK + - MQTT_MESSAGE_SUBSCRIBE + - MQTT_MESSAGE_SUBACK + - MQTT_MESSAGE_PUBLISH + - MQTT_MESSAGE_PUBACK + - MQTT_MESSAGE_PUBREC + - MQTT_MESSAGE_PUBREL + - MQTT_MESSAGE_PUBCOMP + - MQTT_MESSAGE_UNSUBSCRIBE + - MQTT_MESSAGE_UNSUBACK + - MQTT_MESSAGE_PINGREQ + - MQTT_MESSAGE_PINGRESP + - MQTT_MESSAGE_DISCONNECT + - MQTT_MESSAGE_AUTH + state: + type: string + description: Current state of the recording. Only sent by the API, ignored + if specified on POST + enum: + - SCHEDULED + - IN_PROGRESS + - ABORTED + - STOPPED + description: 'Trace recording item describing the desired (and optionally, when + receiving from the server: current) state of a trace recording' + TraceRecordingItem: + required: + - traceRecording type: object properties: - connection: - $ref: '#/components/schemas/Connection' + traceRecording: + $ref: '#/components/schemas/TraceRecording' + TraceRecordingList: + type: object + properties: + items: + type: array + description: List of result items that are returned by this endpoint + items: + $ref: '#/components/schemas/TraceRecording' + Client: + type: object + properties: + id: + type: string + description: List of result items that are returned by this endpoint + ClientList: + type: object + properties: + items: + type: array + description: List of result items that are returned by this endpoint + items: + $ref: '#/components/schemas/Client' + _links: + $ref: '#/components/schemas/PaginationCursor' + PaginationCursor: + type: object + properties: + next: + type: string + description: Links for pagination + nullable: true CertificateInformation: type: object properties: @@ -1081,29 +1510,18 @@ components: $ref: '#/components/schemas/CertificateInformation' description: TLS information nullable: true - Client: - type: object - properties: - id: - type: string - description: List of result items that are returned by this endpoint - ClientList: + Connection: type: object properties: - items: - type: array - description: List of result items that are returned by this endpoint - items: - $ref: '#/components/schemas/Client' - _links: - $ref: '#/components/schemas/PaginationCursor' - PaginationCursor: + connected: + type: boolean + description: If this client is currently connected + description: Information about the client's connection state + ConnectionItem: type: object properties: - next: - type: string - description: Links for pagination - nullable: true + connection: + $ref: '#/components/schemas/Connection' ClientSubscription: type: object properties: @@ -1114,16 +1532,16 @@ components: type: string description: The Quality of Service level enum: - - AT_MOST_ONCE - - AT_LEAST_ONCE - - EXACTLY_ONCE + - AT_MOST_ONCE + - AT_LEAST_ONCE + - EXACTLY_ONCE retainHandling: type: string description: Retain handling option enum: - - SEND - - SEND_IF_NEW_SUBSCRIPTION - - DO_NOT_SEND + - SEND + - SEND_IF_NEW_SUBSCRIPTION + - DO_NOT_SEND retainAsPublished: type: boolean description: The Retain As Published flag diff --git a/src/main/java/com/hivemq/cli/commands/hivemq/export/clients/ClientDetailsRetrieverTask.java b/src/main/java/com/hivemq/cli/commands/hivemq/export/clients/ClientDetailsRetrieverTask.java index d3242c9d9..19aff541d 100644 --- a/src/main/java/com/hivemq/cli/commands/hivemq/export/clients/ClientDetailsRetrieverTask.java +++ b/src/main/java/com/hivemq/cli/commands/hivemq/export/clients/ClientDetailsRetrieverTask.java @@ -31,6 +31,7 @@ import java.util.concurrent.CompletionException; import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; public class ClientDetailsRetrieverTask implements Runnable { @@ -39,6 +40,7 @@ public class ClientDetailsRetrieverTask implements Runnable { final @NotNull BlockingQueue clientIdsQueue; final @NotNull BlockingQueue clientDetailsQueue; final @NotNull Semaphore clientDetailsInProgress; + final @NotNull AtomicBoolean failed = new AtomicBoolean(false); final static int MAX_CONCURRENT_REQUESTS = 100; @@ -58,9 +60,14 @@ public void run() { try { while (!clientIdsFuture.isDone() || !clientIdsQueue.isEmpty()) { + if (failed.get()) { + Logger.error("Retrieval of client details failed"); + throw new CompletionException(new RuntimeException("Retrieval of client details failed")); + } + final String clientId = clientIdsQueue.poll(50, TimeUnit.MILLISECONDS); if (clientId != null) { - final ClientItemApiCallback clientItemApiCallback = new ClientItemApiCallback(clientDetailsQueue, clientDetailsInProgress); + final ClientItemApiCallback clientItemApiCallback = new ClientItemApiCallback(clientDetailsQueue, clientDetailsInProgress, failed); clientDetailsInProgress.acquire(); hivemqRestService.getClientDetails(clientId, clientItemApiCallback); } @@ -68,38 +75,43 @@ public void run() { // Block until all callbacks are finished clientDetailsInProgress.acquire(MAX_CONCURRENT_REQUESTS); - } - catch (final Exception e) { + } catch (final Exception e) { Logger.error(e, "Retrieval of client details failed"); throw new CompletionException(e); } Logger.debug("Finished retrieving client details"); } - private static class ClientItemApiCallback implements ApiCallback { - final @NotNull BlockingQueue clientDetailsQueue; - final @NotNull Semaphore clientDetailsInProgress; + private final @NotNull BlockingQueue clientDetailsQueue; + private final @NotNull Semaphore clientDetailsInProgress; + private final @NotNull AtomicBoolean failed; public ClientItemApiCallback(final @NotNull BlockingQueue clientDetailsQueue, - final @NotNull Semaphore clientDetailsInProgress) { + final @NotNull Semaphore clientDetailsInProgress, final @NotNull AtomicBoolean failed) { this.clientDetailsQueue = clientDetailsQueue; this.clientDetailsInProgress = clientDetailsInProgress; + this.failed = failed; } @Override - public void onFailure(ApiException e, int statusCode, Map> responseHeaders) { - Logger.trace(e,"Failed to retrieve client details"); + public void onFailure(ApiException e, int statusCode, @NotNull Map> responseHeaders) { + //ignore 404 because MQTT client could be non-persistent and disconnected by now + if (e.getCode() != 404) { + Logger.trace(e, "Failed to retrieve client details"); + failed.set(true); + } clientDetailsInProgress.release(); } @Override - public void onSuccess(ClientItem result, int statusCode, Map> responseHeaders) { + public void onSuccess(ClientItem result, int statusCode, @NotNull Map> responseHeaders) { final ClientDetails clientDetails = result.getClient(); if (clientDetails != null) { try { clientDetailsQueue.put(clientDetails); - } catch (InterruptedException ignored) {} + } catch (InterruptedException ignored) { + } } clientDetailsInProgress.release(); @@ -113,4 +125,4 @@ public void onUploadProgress(long bytesWritten, long contentLength, boolean done public void onDownloadProgress(long bytesRead, long contentLength, boolean done) { } } -} \ No newline at end of file +} diff --git a/src/main/java/com/hivemq/cli/commands/hivemq/export/clients/ExportClientsCommand.java b/src/main/java/com/hivemq/cli/commands/hivemq/export/clients/ExportClientsCommand.java index e5e7b4905..e17208227 100644 --- a/src/main/java/com/hivemq/cli/commands/hivemq/export/clients/ExportClientsCommand.java +++ b/src/main/java/com/hivemq/cli/commands/hivemq/export/clients/ExportClientsCommand.java @@ -18,10 +18,7 @@ import com.google.common.base.Throwables; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import com.google.gson.JsonElement; -import com.google.gson.JsonParser; +import com.google.gson.*; import com.hivemq.cli.MqttCLIMain; import com.hivemq.cli.commands.hivemq.export.AbstractExportCommand; import com.hivemq.cli.openapi.ApiException; @@ -37,14 +34,7 @@ import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Date; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.Callable; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Executors; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; +import java.util.concurrent.*; import java.util.function.BiFunction; @@ -106,6 +96,16 @@ public Integer call() throws IOException, InterruptedException, ExecutionExcepti ); final CompletableFuture clientDetailsRetrieverFuture = CompletableFuture.runAsync(clientDetailsRetrieverTask); + //Fix line end character if "\n" or "\r" are passed + switch (csvLineEndCharacter) { + case "\\n": + csvLineEndCharacter = "\n"; + break; + case "\\r": + csvLineEndCharacter = "\r"; + break; + } + // Start writing client details final ClientDetailsCsvWriterTask clientDetailsCsvWriterTask = new ClientDetailsCsvWriterTask( clientDetailsRetrieverFuture, @@ -182,15 +182,23 @@ public ExportCompletedHandler(final @NotNull ClientDetailsCsvWriterTask clientDe public @NotNull Integer apply(Void o, Throwable throwable) { printingScheduler.shutdown(); if (throwable != null) { - System.err.println("\rFailed to retrieve client details: " + Throwables.getRootCause(throwable).getMessage()); if (throwable.getCause() instanceof ApiException) { final ApiException apiException = (ApiException) throwable.getCause(); if (apiException.getResponseBody() != null) { final Gson gson = new GsonBuilder().setPrettyPrinting().create(); - final JsonElement je = JsonParser.parseString(apiException.getResponseBody()); - final String jsonString = gson.toJson(je); - System.err.println(jsonString); + try { + final JsonElement je = JsonParser.parseString(apiException.getResponseBody()); + final String jsonString = gson.toJson(je); + System.err.println("\rFailed to retrieve client details: " + Throwables.getRootCause(throwable).getMessage()); + System.err.println(jsonString); + } catch (final JsonParseException jsonEx) { + System.err.println("\rFailed to retrieve client details. Please check the URL for the HiveMQ REST-API"); + } + } else { + System.err.println("\rFailed to retrieve client details: " + Throwables.getRootCause(throwable).getMessage()); } + } else { + System.err.println("\rFailed to retrieve client details: " + Throwables.getRootCause(throwable).getMessage()); } if (clientDetailsCsvWriterTask.getWrittenClientDetails() > 0) { diff --git a/src/main/java/com/hivemq/cli/rest/HiveMQRestService.java b/src/main/java/com/hivemq/cli/rest/HiveMQRestService.java index f7c12ea31..42afc37da 100644 --- a/src/main/java/com/hivemq/cli/rest/HiveMQRestService.java +++ b/src/main/java/com/hivemq/cli/rest/HiveMQRestService.java @@ -49,13 +49,13 @@ public HiveMQRestService(final @NotNull String host, final double requestPerSeco public ClientList getClientIds(final @Nullable String cursor) throws ApiException { - return clientsApi.mqttClientsGet(2500, cursor); + return clientsApi.getAllMqttClients(2500, cursor); } public Call getClientDetails(final @NotNull String clientId, final @NotNull ApiCallback callback) throws ApiException { - return clientsApi.mqttClientsClientIdGet1Async(clientId, callback); + return clientsApi.getMqttClientDetailsAsync(clientId, callback); }