Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(26181): OpenAPI specs for the bi-directionality features #564

Open
wants to merge 15 commits into
base: master
Choose a base branch
from

Conversation

vanch3d
Copy link
Contributor

@vanch3d vanch3d commented Sep 17, 2024

See https://hivemq.kanbanize.com/ctrl_board/57/cards/26181/details/

This PR is part of the bi-directional epic and adds a proposal for the expected OpenAPI specs of the new features

The changes are as follows:

  • WRITE added to the capability of the protocol adapters
  • Added CRUD operations for handling tags on devices (through their protocol adapter)
  • Added a new Client category of services to handle requests for MQTT client filters
  • Added a new Domain category of services to handle requests for domain tags and topic schema

For the definition and scope of the entities, refer to the bi-directionality MIRO board: https://miro.com/app/board/uXjVKydZ7vo=/#

Problem Details

The PR also corrects the definition of the ProblemDetails specification, RFC9457 (formerly RFC7807).

The OpenAPI specs are copied from the official SmartBear registry, https://github.com/SmartBear-DevRel/problems-registry. They are embedded in the specs but, ideally, they should be used as a reference to an external file. The specs have been added as a separate OpenAPI specs for reference.

Out-of-scope

  • The specification of the bi-directional mapping cannot be represented, as it is "embedded" in the adapters' undocumented config property. A custom endpoint could be created to export the mappings; it will be tried in a further ticket.
  • HiveMQ should define its own Problem Details registry to maximise reuse across products. It will be described in another ticket.

Design

For clarity, a version of the specs containing only the changes can be found below, to be used in Swagger or IntelliJ.

openapi: 3.0.1
info:
  title: HiveMQ Edge REST API
  version: "2024.8-proposal"
tags:
  - description: Interact with protocol adapters.
    name: Protocol Adapters
  - name: Domain
    description: Interact with the elements of the domain conceptualised around the Edge instance
  - name: Client
    description: Interact with MQTT clients connected to the Edge Broker

paths:
  /api/v1/management/protocol-adapters/adapters/{adapterId}/tags:
    get:
      description: Get the domain tags for the device connected through this adapter
      operationId: get-adapter-domainTags
      parameters:
        - description: The name of the adapter to query.
          in: path
          name: adapterId
          required: true
          schema:
            type: string
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DomainTagList'
              examples:
                OPC-UA:
                  # Example OPC-UA data point
                  value:
                    - tag: "opc-ua/pump1/temperature"
                      dataPoint:
                        nodeId: "ns=3;i=1002"
                MODBUS:
                  # Example MODBUS data point
                  value:
                    - tag: "modbus/pump2/temperature"
                      dataPoint:
                        start: 1
                        shift: 24
      summary: Get the domain tags for the device connected through this adapter
      tags:
        - Protocol Adapters
    post:
      description: Add a new domain tag to the specified adapter
      operationId: add-adapter-domainTags
      parameters:
        - description: The adapter type.
          in: path
          name: adapterId
          required: true
          schema:
            type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/DomainTag'
        description: The new domain tag.
        required: true
      responses:
        "200":
          description: Success
      summary: Add a new  domain tag
      tags:
        - Protocol Adapters
  /api/v1/management/protocol-adapters/adapters/{adapterId}/tags/{tagId}:
    delete:
      description: Delete the specified domain tag on the given adapter.
      operationId: delete-adapter-domainTags
      parameters:
        - description: The adapter Id.
          in: path
          name: adapterId
          required: true
          schema:
            type: string
        - description: The tag id.
          in: path
          name: tagId
          required: true
          schema:
            type: string
      responses:
        "200":
          description: Success
      summary: Delete a domain tag
      tags:
        - Protocol Adapters
    put:
      description: Update the domain tag of an adapter
      operationId: update-adapter-domainTags
      parameters:
        - description: The adapter Id.
          in: path
          name: adapterId
          required: true
          schema:
            type: string
        - description: The tag id.
          in: path
          name: tagId
          required: true
          schema:
            type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/DomainTag'
      responses:
        "200":
          description: Success
      summary: Update a domain tag
      tags:
        - Protocol Adapters
 
  /api/v1/management/domain/tags:
    get:
      description: Get the list of all domain tags created in this Edge instance
      operationId: get-domain-tags
      responses:
        "200":
          content:
            application/json:
              schema:
                type: array
                items:
                  type: string
          description: Success
      summary: Get all domain tags
      tags:
        - Domain
  /api/v1/management/domain/tags/schema:
    get:
      description: Get the data schema associated with the specified tags
      operationId: get-tag-schemas
      parameters:
        - description: The list of tags to query the schema from
          in: query
          name: tags
          required: true
          schema:
            type: array
            items:
              type: string
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TagSchema'
          description: Success
      summary: Get data schemas
      tags:
        - Domain
  /api/v1/management/domain/topics:
    get:
      description: Get the list of all topic tags created in this Edge instance
      operationId: get-domain-topics
      responses:
        "200":
          content:
            application/json:
              schema:
                type: array
                items:
                  type: string
          description: Success
      summary: Get all topic tags
      tags:
        - Domain
  /api/v1/management/domain/topics/schema:
    get:
      description: Get the data schema associated with the specified topics
      operationId: get-topic-schemas
      parameters:
        - description: The list of topics to query the schema from
          in: query
          name: topics
          required: true
          schema:
            type: array
            items:
              type: string
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TagSchema'
          description: Success
      summary: Get data schemas
      tags:
        - Domain

  /api/v1/management/client/topic-samples:
    get:
      description: Get a sample of MQTT topics published by clients connected to the Edge broker over a period of time
      operationId: get-client-topics
      parameters:
        - description: The time limit for the observation.
          in: query
          name: queryTime
          required: true
          schema:
            type: integer
            minimum: 500
            default: 1000
            maximum: 10000
      responses:
        "200":
          content:
            application/json:
              example:
                items:
                  - client1/topic1
                  - client1/topic2
                  - client2/topic1
              schema:
                $ref: '#/components/schemas/ClientTopicList'
          description: Success
      summary: Get a sample of MQTT topics
      tags:
        - Client
  /api/v1/management/client/filters:
    get:
      description: Get a list of all clients filters created for the Edge instance
      operationId: get-client-filters
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ClientFilterList'
          description: Success
      summary: Get a list of MQTT client filters
      tags:
        - Client
    post:
      description: Add a client filter to the Edge instance
      operationId: add-client-filter
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ClientFilter'
        description: The new client filter
        required: true
      responses:
        "200":
          description: Success
      summary: Add a client filter
      tags:
        - Client
  /api/v1/management/client/filters/{clientFilterId}:
    get:
      description: Get the details of the specified client filter and its topcis
      operationId: get-client-filter
      parameters:
        - description: The client filter Id.
          in: path
          name: clientFilterId
          required: true
          schema:
            type: string
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ClientFilter'
          description: Success
      summary: Get a MQTT client filter
      tags:
        - Client
    delete:
      description: Delete the specified client filter.
      operationId: delete-client-filter
      parameters:
        - description: The client filter Id.
          in: path
          name: clientFilterId
          required: true
          schema:
            type: string
      responses:
        "200":
          description: Success
      summary: Delete a client filter
      tags:
        - Client
    put:
      description: Update the specified client filter
      operationId: update-client-filter
      parameters:
        - description: The client filter Id.
          in: path
          name: clientFilterId
          required: true
          schema:
            type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ClientFilter'
      responses:
        "200":
          description: Success
      summary: Update a client filter
      tags:
        - Client
components:
  schemas:
    QoS:
      type: integer
      format: int32
      default: 0
      description: The maxQoS for this subscription.
      enum:
        - 0
        - 1
        - 2
    ClientFilterConfiguration:
      type: object
      required:
        - destination
      properties:
        destination:
          type: string
        maxQoS:
          $ref: '#/components/schemas/QoS'
    ClientFilter:
      type: object
      description: A client filter
      properties:
        id:
          type: string
          description: The unique id of the client filter
        topicFilters:
          type: array
          description: The list of topics associated with this client filter
          items:
            $ref: '#/components/schemas/ClientFilterConfiguration'
      required:
        - id
        - topicFilters
    ClientFilterList:
      type: array
      description: List of result items that are returned by this endpoint
      items:
        $ref: '#/components/schemas/ClientFilter'
    DeviceDataPoint:
      ### TODO We need to name that entity
      type: object
      description: A data point on a device connected to the adapter
    DomainTag:
      type: object
      description: A tag associated with a data point on a device connected to the adapter
      properties:
        tag:
          type: string
          description: The Tag associated with the data-point.
        dataPoint:
          $ref: '#/components/schemas/DeviceDataPoint'
      required:
        - tag
        - dataPoint
    DomainTagList:
      type: object
      properties:
        items:
          type: array
          description: List of result items that are returned by this endpoint
          items:
            $ref: '#/components/schemas/DomainTag'
    ClientTopicList:
      type: object
      properties:
        items:
          type: array
          description: List of result topics that are returned by this endpoint
          items:
            type: string
  
    ProtocolAdapter:
      type: object
      description: List of result items that are returned by this endpoint
      properties:
        author:
          type: string
          description: The author of the adapter
        capabilities:
          type: array
          description: The capabilities of this adapter
          items:
            type: string
            description: The capabilities of this adapter
            enum:
              - WRITE
              - READ
              - DISCOVER
          uniqueItems: true
    TagSchema:
      type: object
      description: The JSON-Schema specification of a data point

@sfrehse
Copy link
Contributor

sfrehse commented Sep 17, 2024

@vanch3d, it's great that you come up with the proposal. Do you have any idea how we can better review that? The view in GH is not optimal to comment :-)

tags:
- Domain

/api/v1/management/client/topic-samples:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this needed?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is this path under the root '/client' but topics are under the root '/domain' ?

@vanch3d vanch3d force-pushed the chore/26181/bi-directionality-openAPI branch from 6c0238f to b909d6f Compare September 23, 2024 14:44
- fix response of domain/tags/schema
- create TagSchemaList
- rename DeviceDataPoint into DomainTagAddress
- add additionalProperties to schema
@h2xd
Copy link
Contributor

h2xd commented Sep 27, 2024

Big supporter of this, as this gives not only more insights to the Frontend Engineers but also later customer that consume potentially the API. This would allow the customers to react to errors and build more recoverable services.

it's great that you come up with the proposal. Do you have any idea how we can better review that? The view in GH is not optimal to comment :-)

Agree with @sfrehse here it's really hard to get into.

summary: Get data schemas
tags:
- Domain
/api/v1/management/domain/topics:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this only for publish 'topics' or also for subscribe 'topicFilters' ?

application/json:
example:
items:
- client1/topic1
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i dont understand the examples. wouldnt it be something like:
{
"clientId" : "my-fancy-client",
"topic": "a/b/c"
}

description: Get a sample of MQTT topics published by clients connected to the Edge broker over a period of time
operationId: get-client-topics
parameters:
- description: The time limit for the observation.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in seconds or milliseconds?

schema:
type: integer
minimum: 500
default: 1000
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in millis, the default seems a bit short, there can be nothing. in seconds its far to long, we cant cache topic data for so long

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants