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

feat: create Anypoint MQ bindings #63

Merged
Merged
Show file tree
Hide file tree
Changes from 33 commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
7477345
added Anypoint MQ skeleton
GeraldLoeffler Mar 10, 2021
9fbdb65
refined wording
GeraldLoeffler Mar 10, 2021
5057fca
draft of server binding object
GeraldLoeffler Mar 11, 2021
78ab493
tentatively complete server binding object
GeraldLoeffler Mar 15, 2021
f5d0dc6
fleshed-out skeleton of remaining sections
GeraldLoeffler Mar 15, 2021
3c713f3
added remaining empty JSON schema docs
GeraldLoeffler Mar 15, 2021
5df74b0
added backwards compatiblity
GeraldLoeffler Mar 15, 2021
d0e0309
better description of backwards compatibility
GeraldLoeffler Mar 15, 2021
c031611
first take on channel binding object: probably need to eliminate this
GeraldLoeffler Mar 18, 2021
271567d
empty channel binding object
GeraldLoeffler Mar 18, 2021
1e7e6a2
elaborated on code generation
GeraldLoeffler Mar 18, 2021
20ebdd4
elaborated on code generation
GeraldLoeffler Mar 18, 2021
620a780
ci: update global workflows (#57)
asyncapi-bot Mar 29, 2021
18cbb5c
ci: update global workflows (#58)
asyncapi-bot Apr 2, 2021
8146e1d
ci: update global workflows (#59)
asyncapi-bot Apr 6, 2021
c3c2825
Merge pull request #2 from asyncapi/master
GeraldLoeffler Apr 9, 2021
312d58e
progressing...
GeraldLoeffler Apr 9, 2021
778d43a
switching to new schema naming convention
GeraldLoeffler Apr 26, 2021
14dfc58
added bindingVersion
GeraldLoeffler Apr 26, 2021
5e8aed9
fine-tuning
GeraldLoeffler Apr 26, 2021
d7f3495
Merge branch 'asyncapi:master' into master
GeraldLoeffler May 26, 2021
b179ca9
moving towards minimalistic bindings spec
GeraldLoeffler May 26, 2021
290395d
simplified up to server object
GeraldLoeffler May 27, 2021
33405de
working on channel
GeraldLoeffler May 27, 2021
14c9864
up to message binding
GeraldLoeffler May 27, 2021
bc95058
refining
GeraldLoeffler May 27, 2021
d55f6f2
refining
GeraldLoeffler May 27, 2021
548f92d
add complete example
GeraldLoeffler May 28, 2021
9fc597a
refining
GeraldLoeffler May 28, 2021
210d17b
refining
GeraldLoeffler May 28, 2021
08eff62
refining
GeraldLoeffler May 28, 2021
6c12809
schemata
GeraldLoeffler May 28, 2021
fcba4c3
Merge branch 'asyncapi:master' into anypointmq-bindings-minimalistic
GeraldLoeffler May 28, 2021
c327d2e
corrected message binding object to use schema for headers; fixed som…
GeraldLoeffler Jun 10, 2021
a8de5da
fixed schema object link
GeraldLoeffler Jun 10, 2021
bba62d0
fix leftover props
GeraldLoeffler Jun 10, 2021
0b7b796
removing mention of AsyncAPI version
GeraldLoeffler Jul 27, 2021
e1b1abf
eliminated server and operation binding objects
GeraldLoeffler Aug 25, 2021
b9c46ed
Delete server.json
GeraldLoeffler Aug 25, 2021
03cf865
Delete operation.json
GeraldLoeffler Aug 25, 2021
72c59e4
Merge branch 'asyncapi:master' into anypointmq-bindings-minimalistic
GeraldLoeffler Sep 15, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
286 changes: 286 additions & 0 deletions anypointmq/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,286 @@
# Anypoint MQ Bindings

This document defines how to describe Anypoint MQ-specific information in AsyncAPI documents.

[Anypoint MQ](https://docs.mulesoft.com/mq/) is MuleSoft's multi-tenant, cloud messaging service and is fully integrated with [Anypoint Platform](https://www.mulesoft.com/platform/enterprise-integration).

<a name="version"></a>
## Versions

The version of this bindings specification is `0.0.1`.
This is also the `bindingVersion` for all binding objects defined by this specification.
In any given binding object, `latest` MAY alternatively be used to refer to the currently latest published version of this bindings specification.

The version of the AsyncAPI specification to which these bindings apply is `2.1.0`.
Copy link
Member

Choose a reason for hiding this comment

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

Do we need to have this here? Why couldn't this binding be applied to a potential 2.2.0 or 2.1.1 version?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Do we need to have this here? Why couldn't this binding be applied to a potential 2.2.0 or 2.1.1 version?

i noticed that none of the other binding specs are tied to a spec version, but in writing the binding spec i definitely had in mind to close the gap between AsyncAPI 2.0.0 and the Anypoint MQ protocol. So i considered it prudent to state that. In truth the binding spec also applies to 2.1.0 as far as i can tell.

@fmvilas : If you are opposed to binding specs being explicitly tied to AsyncAPI spec versions, then i'll remove this. Let me know.

Copy link
Member

Choose a reason for hiding this comment

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

I'm not opposed but I think we should align in the way we do it, so the rest of the bindings can do it in the same way. Would you mind opening a separate issue for that and removing this line for now?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

and removed the line from the binding spec.


## Terminology

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this bindings specification are to be interpreted as described in IETF [RFC2119](https://www.ietf.org/rfc/rfc2119.txt).

## Protocol

These bindings use the `anypointmq` [protocol](https://github.com/asyncapi/spec/blob/master/spec/asyncapi.md#definitionsProtocol) in AsyncAPI documents to denote connections to and interactions with Anypoint MQ message brokers.

The Anypoint MQ protocol is based on invocations of the [Anypoint MQ Broker REST API](https://docs.mulesoft.com/mq/mq-apis#mqbrokerapi).

## Server Object

The fields of the standard [Server Object](https://github.com/asyncapi/spec/blob/master/spec/asyncapi.md#serverObject) are constrained and interpreted as follows:

Server Object Field Name | Values for Anypoint MQ Protocol | Description
---|:---|:---
<a name="serverObjectProtocolFieldValueAnypointMQ"></a>`protocol` | `anypointmq` | **Required**. MUST be `anypointmq` for the scope of this specification.
<a name="serverObjectUrlFieldValueAnypointMQ"></a>`url` | e.g., `https://mq-us-east-1.anypoint.mulesoft.com/api` | **Required**. MUST be the endpoint URL of the Anypoint MQ Broker REST API _excluding_ the final major version indicator (e.g., `v1`). Valid examples are `https://mq-us-east-1.anypoint.mulesoft.com/api` and `https://mq-eu-central-1.eu1.anypoint.mulesoft.com/api` (and _not_ `https://.../api/v1`).
<a name="serverObjectProtocolVersionFieldValueAnypointMQ"></a>`protocolVersion` | e.g., `v1` | **Optional**, defaults to `v1`. If present MUST be the major version indicator of the Anypoint MQ Broker REST API omitted from the `url`, e.g. `v1`.
<a name="serverObjectSecurityFieldValueAnypointMQ"></a>`security` | suitably configured OAuth 2.0 client credentials grant type | **Required**. Authentication against the MuleSoft-hosted Anypoint MQ message brokers uses the OAuth 2.0 client credentials grant type. At runtime, the client ID and client secret values of an Anypoint MQ client app must be supplied. Also, the OAuth 2.0 scopes are currently not client-configurable. The `security` field of the server object MUST correctly match these constraints.

Note that the choice of a particular Anypoint MQ client app (via its client ID and secret) decides the Anypoint Platform organization ID and environment (ID) to be those in which this client app is defined. See the [Anypoint MQ documentation](https://docs.mulesoft.com/mq/mq-client-apps) for details on how to configure Anypoint MQ client apps.

<a name="server"></a>
## Server Binding Object

The Anypoint MQ [Server Binding Object](https://github.com/asyncapi/spec/blob/master/spec/asyncapi.md#serverBindingsObject) is defined by a [JSON Schema](json_schemas/server.json), which currently defines only the *optional* `bindingVersion` field:

Field Name | Type | Description
---|:---:|---
<a name="serverBindingObjectBindingVersion"></a>`bindingVersion` | string | **Optional**, defaults to `latest`. The version of this binding.

### Examples

The following example shows a `servers` object with two servers, both using `anypointmq` as the `protocol`, the second having a server binding object for `anypointmq`:

```yaml
servers:
development:
url: https://mq-us-east-1.anypoint.mulesoft.com/api
description: |
Anypoint MQ broker for development, in the US East (N. Virginia) runtime plane under management of the US control plane.
Implicitly uses v1 of the anypointmq protocol and hence the Anypoint MQ Broker REST API.
Minimal configuration, omitting a server binding object.
protocol: anypointmq

production:
url: https://mq-eu-central-1.eu1.anypoint.mulesoft.com/api
description: |
Anypoint MQ broker for production, in the EU Central (Frankfurt) runtime plane under management of the EU control plane.
Explicitly specifies the use of v1 of the anypointmq protocol and hence the Anypoint MQ Broker REST API.
Explicitly provides a server binding object.
protocol: anypointmq
protocolVersion: v1
bindings:
anypointmq:
bindingVersion: '0.0.1'
```

<a name="channel"></a>
## Channel Binding Object

The Anypoint MQ [Channel Binding Object](https://github.com/asyncapi/spec/blob/master/spec/asyncapi.md#channel-bindings-object) is defined by a [JSON Schema](json_schemas/channel.json), which defines these fields:

Field Name | Type | Description
---|:---:|---
<a name="channelBindingObjectDestination"></a>`destination` | string | **Optional**, defaults to the channel name. The destination (queue or exchange) name for this channel. SHOULD only be specified if the channel name differs from the actual destination name, such as when the channel name is not a valid destination name in Anypoint MQ.
<a name="channelBindingObjectType"></a>`destinationType` | string | **Optional**, defaults to `queue`. The type of destination, which MUST be either `exchange` or `queue` or `fifo-queue`. SHOULD be specified to document the messaging model (publish/subscribe, point-to-point, strict message ordering) supported by this channel.
<a name="channelBindingObjectBindingVersion"></a>`bindingVersion` | string | **Optional**, defaults to `latest`. The version of this binding.

Note that an Anypoint MQ exchange can only be sent to, not received from. To receive messages sent to an exchange, [an intermediary queue must be defined and bound to the exchange](https://docs.mulesoft.com/mq/mq-understanding#message-exchanges). In this bindings specification, these intermediary queues are not exposed in the AsyncAPI document. Instead, it is simply assumed that whenever messages must be received from an exchange, such an intermediary queue is involved yet invisible in the AsyncAPI document.

### Examples

The following example shows a `channels` object with two channels, the second having a channel binding object for `anypointmq`:

```yaml
channels:
user/signup:
description: |
This application receives command messages from this channel about users to sign up.
Minimal configuration, omitting a channel binding object.
publish:
#...
user/signedup:
description: |
This application sends events to this channel about users that have signed up.
Explicitly provides a channel binding object.
bindings:
anypointmq:
destination: user-signup-exchg
destinationType: exchange
bindingVersion: '0.0.1'
subscribe:
#...
```

<a name="operation"></a>
## Operation Binding Object

The Anypoint MQ [Operation Binding Object](https://github.com/asyncapi/spec/blob/master/spec/asyncapi.md#operation-bindings-object) is defined by a [JSON Schema](json_schemas/operation.json), which currently defines only the *optional* `bindingVersion` field:

Field Name | Type | Description
---|:---:|---
<a name="operationBindingObjectBindingVersion"></a>`bindingVersion` | string | **Optional**, defaults to `latest`. The version of this binding.

### Examples

The following example shows a `channels` object with two channels, each having one operation (`subscribe` or `publish`). Only the `subscribe` operation has an operation binding object for `anypointmq`:

```yaml
channels:
user/signup:
publish:
operationId: signUpUser
description: |
This application receives command messages via this operation about users to sign up.
Minimal configuration, omitting an operation binding object.
message:
#...
user/signedup:
subscribe:
operationId: userHasSignedUp
description: |
This application sends events via this operation about users that have signed up.
Explicitly provides an operation binding object.
bindings:
anypointmq:
bindingVersion: '0.0.1'
message:
#...
```

<a name="message"></a>
## Message Binding Object

The Anypoint MQ [Message Binding Object](https://github.com/asyncapi/spec/blob/master/spec/asyncapi.md#message-bindings-object) is defined by a [JSON Schema](json_schemas/message.json), which defines these fields:

Field Name | Type | Description
---|:---:|---
<a name="messageBindingObjectMessageId"></a>`messageId` | string | **Optional**. The unique ID of the message. When publishing the message, if not specified, the broker creates a unique message ID. This is transmitted as a protocol header in the Anypoint MQ message `headers` section.
<a name="messageBindingObjectMessageGroupId"></a>`messageGroupId` | string | **Optional**. The ID of the message group to which the message belongs. Applies only to FIFO queues. Message group IDs can contain up to 128 alphanumeric and punctuation characters. This is transmitted as a protocol header in the Anypoint MQ message `headers` section.
<a name="messageBindingObjectBindingVersion"></a>`bindingVersion` | string | **Optional**, defaults to `latest`. The version of this binding.

Note that message headers, which are specified in the `headers` field of the standard [Message Object](https://github.com/asyncapi/spec/blob/master/spec/asyncapi.md#messageObject), are transmitted in the [Anypoint MQ message `properties` section](https://docs.mulesoft.com/mq/mq-apis#example-publish-a-message). In AsyncAPI, this `headers` field does not include protocol headers such as `messageId` or `messageGroupId`, which are transmitted in the [Anypoint MQ message `headers` section](https://docs.mulesoft.com/mq/mq-apis#postsetup).

Please note that the definition of this message binding object is likely to change in future versions of this bindings specification to better describe the mapping of the fields of the AsyncAPI standard message object to the various parts of the Anypoint MQ message as it is exchanged as an HTTP body with the Anypoint MQ Broker REST API.

### Examples

The following example shows a `channels` object with two channels, each having one operation (`subscribe` or `publish`) with one message. Only the message of the `subscribe` operation has a message binding object for `anypointmq`:

```yaml
channels:
user/signup:
publish:
message:
#...
user/signedup:
subscribe:
message:
headers:
type: object
properties:
correlationId:
description: Correlation ID set by application
type: string
payload:
type: object
properties:
#...
correlationId:
description: Correlation ID is specified as a header and transmitted in the Anypoint MQ message properties section
location: $message.header#/correlationId
bindings:
anypointmq:
messageId: 'e0c62826-52d9-4d64-bdd8-a7c415917acf'
messageGroupId: '42'
bindingVersion: '0.0.1'
```

## Complete Example

The following is a complete, simple AsyncAPI document illustrating the usage of all binding objects defined in this bindings specification, with all their fields.

```yaml
asyncapi: '2.0.0'
info:
title: Example with Anypoint MQ
version: '0.0.1'

servers:
development:
protocol: anypointmq
protocolVersion: v1
url: https://mq-us-east-1.anypoint.mulesoft.com/api
description: |
Anypoint MQ broker for development, in the US East (N. Virginia) runtime plane
under management of the US control plane.
security:
- oauthDev: []
bindings:
anypointmq:
bindingVersion: '0.1.0'
production:
protocol: anypointmq
protocolVersion: v1
url: https://mq-eu-central-1.eu1.anypoint.mulesoft.com/api
description: |
Anypoint MQ broker for production, in the EU Central (Frankfurt) runtime plane
under management of the EU control plane.
security:
- oauthProd: []
bindings:
anypointmq:
bindingVersion: '0.1.0'

channels:
user/signup:
description: |
This application receives command messages from this channel about users to sign up.
bindings:
anypointmq:
destination: user-signup-queue
destinationType: fifo-queue
bindingVersion: '0.1.0'
publish:
operationId: signUpUser
description: |
This application receives command messages via this operation about users to sign up.
bindings:
anypointmq:
bindingVersion: '0.1.0'
message:
contentType: application/json
headers:
type: object
properties:
correlationId:
description: Correlation ID set by application
type: string
payload:
type: object
properties:
username:
type: string
minLength: 3
correlationId:
description: Correlation ID is specified as a header and transmitted in the Anypoint MQ message properties section
location: $message.header#/correlationId
bindings:
anypointmq:
messageId: 'e0c62826-52d9-4d64-bdd8-a7c415917acf'
messageGroupId: '42'
bindingVersion: '0.1.0'

components:
securitySchemes:
oauthDev:
type: oauth2
flows:
clientCredentials:
tokenUrl: https://mq-us-east-1.anypoint.mulesoft.com/api/v1/authorize
scopes: {}
oauthProd:
type: oauth2
flows:
clientCredentials:
tokenUrl: https://mq-eu-central-1.eu1.anypoint.mulesoft.com/api/v1/authorize
scopes: {}
```
40 changes: 40 additions & 0 deletions anypointmq/json_schemas/channel.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "http://asyncapi.com/bindings/anypointmq/channel.json",
"title": "Channel Schema",
"description": "This object contains configuration for describing an Anypoint MQ exchange, queue, or FIFO queue as an AsyncAPI channel. This objects only contains configuration that can not be provided in the AsyncAPI standard channel object.",
"type": "object",
"additionalProperties": false,
"patternProperties": {
"^x-[\\w\\d\\.\\-\\_]+$": {
"$ref": "https://raw.githubusercontent.com/asyncapi/asyncapi-node/v2.7.7/schemas/2.0.0.json#/definitions/specificationExtension"
}
},
"properties": {
"destination": {
"type": "string",
"description": "The destination (queue or exchange) name for this channel. SHOULD only be specified if the channel name differs from the actual destination name, such as when the channel name is not a valid destination name in Anypoint MQ. Defaults to the channel name."
},
"destinationType": {
"type": "string",
"enum": ["exchange", "queue", "fifo-queue"],
"default": "queue",
"description": "The type of destination. SHOULD be specified to document the messaging model (publish/subscribe, point-to-point, strict message ordering) supported by this channel."
},
"bindingVersion": {
"type": "string",
"enum": [
"0.0.1"
],
"description": "The version of this binding. If omitted, 'latest' MUST be assumed."
}

},
"examples": [
{
"destination": "user-signup-exchg",
"destinationType": "exchange",
"bindingVersion": "0.0.1"
}
]
}
38 changes: 38 additions & 0 deletions anypointmq/json_schemas/message.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "http://asyncapi.com/bindings/anypointmq/message.json",
"title": "Message Schema",
"description": "This object contains configuration for describing an Anypoint MQ message as an AsyncAPI message. This objects only contains configuration that can not be provided in the AsyncAPI standard message object.",
"type": "object",
"additionalProperties": false,
"patternProperties": {
"^x-[\\w\\d\\.\\-\\_]+$": {
"$ref": "https://raw.githubusercontent.com/asyncapi/asyncapi-node/v2.7.7/schemas/2.0.0.json#/definitions/specificationExtension"
}
},
"properties": {
"messageId": {
"type": "string",
"description": "The unique ID of the message. When publishing the message, if not specified, the broker creates a unique message ID. This is transmitted as a protocol header in the Anypoint MQ message `headers` section."
},
"messageGroupId": {
"type": "string",
"description": "The ID of the message group to which the message belongs. Applies only to FIFO queues. Message group IDs can contain up to 128 alphanumeric and punctuation characters. This is transmitted as a protocol header in the Anypoint MQ message `headers` section."
},
"bindingVersion": {
"type": "string",
"enum": [
"0.0.1"
],
"description": "The version of this binding. If omitted, 'latest' MUST be assumed."
}

},
"examples": [
{
"messageId": "e0c62826-52d9-4d64-bdd8-a7c415917acf",
"messageGroupId": "42",
"bindingVersion": "0.0.1"
}
]
}
27 changes: 27 additions & 0 deletions anypointmq/json_schemas/operation.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "http://asyncapi.com/bindings/anypointmq/operation.json",
"title": "Operation Schema",
"description": "This object contains configuration for describing sending or receiving an Anypoint MQ message as an AsyncAPI operation. This objects only contains configuration that can not be provided in the AsyncAPI standard operation object.",
"type": "object",
"additionalProperties": false,
"patternProperties": {
"^x-[\\w\\d\\.\\-\\_]+$": {
"$ref": "https://raw.githubusercontent.com/asyncapi/asyncapi-node/v2.7.7/schemas/2.0.0.json#/definitions/specificationExtension"
}
},
"properties": {
"bindingVersion": {
"type": "string",
"enum": [
"0.0.1"
],
"description": "The version of this binding. If omitted, 'latest' MUST be assumed."
}
},
"examples": [
{
"bindingVersion": "0.0.1"
}
]
}
Loading